Producer-consumerpatroon
Implementeer een producer-consumer-pijplijn met coroutines
Producer-consumerpatroon is een gratis Lua Academy-les op CoddyKit. Dit is les 4 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Lua Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Lua Academy bevat in totaal 4 lessen.
Het patroon uitgelegd
Het producent-consumentpatroon met coroutines: de producent genereert gegevens en levert elk item op; de consument ontvangt de items één voor één. Geen van beide hoeft de implementatie van de ander te kennen — ze communiceren via yield/resume. Hierdoor worden het genereren en verwerken van gegevens van elkaar losgekoppeld.
local function makeProducer(items)
return coroutine.create(function()
for _, item in ipairs(items) do
coroutine.yield(item)
end
end)
end
local function consume(producer)
while true do
local ok, item = coroutine.resume(producer)
if not ok or item == nil then break end
print("Processing:", item)
end
end
consume(makeProducer({10, 20, 30, 40}))Oneindige producent
Een producent-coroutine kan een oneindige reeks opleveren. De consument bepaalt wanneer hij stopt. Dit is ideaal voor gegevensbronnen die gegevens streamen, zoals sensormetingen, loggebeurtenissen en gegenereerde reeksen.
local function primes()
return coroutine.wrap(function()
local function isPrime(n)
if n<2 then return false end
for i=2, math.floor(math.sqrt(n)) do
if n%i==0 then return false end
end
return true
end
local n = 2
while true do
if isPrime(n) then coroutine.yield(n) end
n = n + 1
end
end)
end
local gen = primes()
for i = 1, 10 do
io.write(gen() .. " ")
end
print() -- 2 3 5 7 11 13 17 19 23 29Consument als coroutine
De consument kan ook een coroutine zijn, waardoor een volledig symmetrisch producent-consumentpaar ontstaat. Een derde functie, de "aanstuurfunctie", coördineert beide. Dit is nuttig voor gebufferde pijplijnen waarin producent en consument verschillende snelheden hebben.
local function producer()
return coroutine.create(function(consumer)
for i = 1, 5 do
coroutine.resume(consumer, i * 10)
coroutine.yield() -- wait
end
end)
end
local consumer = coroutine.create(function()
while true do
local val = coroutine.yield()
print("Received:", val)
end
end)
coroutine.resume(consumer) -- start, waits for data
local pro = producer()
for i = 1, 5 do
coroutine.resume(pro, consumer)
endTerugdruk
Terugdruk ontstaat wanneer de consument de producent laat vertragen. Met coroutines gaat dit vanzelf: de producent voert na elk item yield uit en wacht tot de consument het volgende item opvraagt. Als de consument traag is, wacht de producent gewoon.
local function slowConsumer(gen)
for v in gen do
-- Simulate slow processing
print("Processing", v, "...")
-- In real code: os.execute("sleep 0.1")
end
end
local function fastProducer(n)
return coroutine.wrap(function()
for i = 1, n do
print("Producing", i)
coroutine.yield(i)
end
end)
end
-- Producer automatically waits for consumer:
slowConsumer(fastProducer(4))Verwerking in batches
Een producent die in batches werkt, verzamelt N items voordat hij een batch oplevert. De consument ontvangt en verwerkt volledige batches. Hierdoor neemt de coördinatie-overhead voor producenten met een hoge frequentie af.
local function batchProducer(items, batchSize)
return coroutine.wrap(function()
local batch = {}
for _, item in ipairs(items) do
batch[#batch+1] = item
if #batch >= batchSize then
coroutine.yield(batch)
batch = {}
end
end
if #batch > 0 then coroutine.yield(batch) end
end)
end
local data = {1,2,3,4,5,6,7,8,9,10}
for batch in batchProducer(data, 3) do
print("Batch:", table.concat(batch, ","))
end
-- Batch: 1,2,3
-- Batch: 4,5,6
-- Batch: 7,8,9
-- Batch: 10Producent van bestandsregels
Lees een bestand lui: een producent-coroutine leest de regels één voor één en levert elke regel op. De consument verwerkt de regels zonder het volledige bestand in het geheugen te laden.
local function lineProducer(path)
return coroutine.wrap(function()
local f = io.open(path, "r")
if not f then return end
for line in f:lines() do
coroutine.yield(line)
end
f:close()
end)
end
-- Process file line by line without loading all at once
local wordCount = 0
for line in lineProducer("data.txt") do
for _ in line:gmatch("%S+") do
wordCount = wordCount + 1
end
end
print("Words:", wordCount)Transformatiefase
Voeg een transformatiefase toe tussen producent en consument. De transformatie leest van één coroutine en levert verwerkte waarden aan een andere. Bouw gegevenspijplijnen door deze fasen aan elkaar te koppelen.
local function transform(source, fn)
return coroutine.wrap(function()
for v in source do
coroutine.yield(fn(v))
end
end)
end
local numbers = coroutine.wrap(function()
for i = 1, 6 do coroutine.yield(i) end
end)
local doubled = transform(numbers, function(n) return n*2 end)
local filtered = coroutine.wrap(function()
for v in doubled do
if v > 4 then coroutine.yield(v) end
end
end)
for v in filtered do io.write(v.." ") end
print() -- 6 8 10 12Foutdoorgifte in pijplijnen
Fouten in coroutinepijplijnen worden doorgegeven via de toestand beëindigd of via pcall. Wikkel pijplijnfasen in pcall om fouten op te vangen en netjes af te handelen zonder de hele pijplijn te laten crashen.
local function safeStage(source, fn)
return coroutine.wrap(function()
for v in source do
local ok, result = pcall(fn, v)
if ok then
coroutine.yield(result)
else
print("Error processing", v, ":", result)
end
end
end)
end
local data = coroutine.wrap(function()
for _, v in ipairs({4, -1, 9, 0, 16}) do coroutine.yield(v) end
end)
local results = safeStage(data, function(n)
assert(n > 0, "non-positive")
return math.sqrt(n)
end)
for v in results do print(v) endProducenten samenvoegen
Combineer meerdere producenten tot één producent: ga in een round-robinpatroon langs alle actieve producenten en lever telkens één item op. Stop wanneer alle producenten zijn uitgeput.
local function merge(...)
local producers = {...}
return coroutine.wrap(function()
while #producers > 0 do
local alive = {}
for _, co in ipairs(producers) do
local ok, v = coroutine.resume(co)
if ok and v ~= nil then
coroutine.yield(v)
alive[#alive+1] = co
end
end
producers = alive
end
end)
end
local function src(items)
return coroutine.create(function()
for _,v in ipairs(items) do coroutine.yield(v) end
end)
end
for v in merge(src({1,3,5}),src({2,4,6})) do
io.write(v.." ")
end
print() -- 1 2 3 4 5 6Praktijkvoorbeeld
Pijplijn voor logverwerking: de producent leest logregels, de filterfase houdt alleen foutregels over, de transformatiefase haalt belangrijke informatie eruit en de consument groepeert op fouttype. Elke fase is een onafhankelijke coroutine die afzonderlijk kan worden getest.
local function makeFilter(src, pred)
return coroutine.wrap(function()
for line in src do
if pred(line) then coroutine.yield(line) end
end
end)
end
local logs = coroutine.wrap(function()
local entries = {
"INFO: started",
"ERROR: timeout",
"DEBUG: connecting",
"ERROR: auth failed",
}
for _, e in ipairs(entries) do coroutine.yield(e) end
end)
local errors = makeFilter(logs, function(l) return l:match("^ERROR") end)
for line in errors do print(line) end
-- ERROR: timeout
-- ERROR: auth failedSnelle controle
Hoe handelt het producent-consumentpatroon met coroutines terugdruk af?
Samenvatting: producent-consument
Samenvatting:
- De producent levert items op; de consument stuurt aan door resume aan te roepen
- Oneindige producenten:
while true do yield() end - Pijplijnen: koppel transformatiecoroutines tussen producent en consument
- Terugdruk gebeurt automatisch: de producent wacht op de consument
- Gebruik batch-, filter- en samenvoegfasen als coroutinewrappers
- Gebruik pcall in pijplijnfasen om fouten van elkaar te isoleren
Leer Lua met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 40
- Lessen
- 159
Veelgestelde vragen
Is de les “Producer-consumerpatroon” gratis?
Ja — je kunt hier op het web alle 3 lessen van het leerpad Lua Academy, waaronder “Producer-consumerpatroon”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Lua Academy bevat in totaal 4 lessen.
Wat leer ik in “Producer-consumerpatroon”?
Implementeer een producer-consumer-pijplijn met coroutines Je oefent met Lua Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Lua Academy te beginnen?
Ervaring vooraf is niet nodig. Lua Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.
Hoe lang duurt de les “Producer-consumerpatroon”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Lua Academy?
Ja. Elke les over Lua Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Coroutines maken
- resume en yield
- Coroutine-status
- Producer-consumerpatroon