نمط المنتج والمستهلك
نفّذ خط أنابيب المنتج والمستهلك باستخدام البرامج التعاونية
نمط المنتج والمستهلك درس مجاني في Lua Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Lua Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Lua Academy 4 دروس في المجموع.
شرح النمط
نمط المنتج والمستهلك باستخدام الكوروتينات: ينشئ المنتج البيانات وينفذ yield لكل عنصر؛ ويتلقى المستهلك العناصر واحدًا تلو الآخر. ولا يحتاج أي منهما إلى معرفة كيفية تنفيذ الآخر؛ إذ يتواصلان عبر yield/resume. وبهذا ينفصل توليد البيانات عن معالجتها.
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}))منتج لا نهائي
يمكن لكوروتين المنتج إنشاء تسلسل لا نهائي باستخدام yield. ويتحكم المستهلك في وقت التوقف. وهذا مناسب تمامًا لمصادر البيانات المتدفقة، مثل قراءات المستشعرات وأحداث السجل والتسلسلات المُولّدة.
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 29المستهلك بوصفه كوروتينًا
يمكن أن يكون المستهلك كوروتينًا أيضًا، مما ينشئ زوجًا متماثلًا بالكامل من المنتج والمستهلك. وتتولى دالة ثالثة تسمى «المشغّل» تنسيق عملهما. ويفيد ذلك في خطوط الأنابيب ذات التخزين المؤقت، حيث يختلف معدلا المنتج والمستهلك.
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)
endالضغط العكسي
يحدث الضغط العكسي عندما يشير المستهلك إلى المنتج بضرورة الإبطاء. وباستخدام الكوروتينات، يحدث ذلك بصورة طبيعية: ينفذ المنتج yield بعد كل عنصر، وينتظر أن يطلب المستهلك العنصر التالي. وإذا كان المستهلك بطيئًا، ينتظر المنتج ببساطة.
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))المعالجة على دفعات
يجمع المنتج الذي يستخدم الدفعات عددًا قدره N من العناصر قبل تنفيذ yield لإرجاع دفعة. ويتلقى المستهلك الدفعات الكاملة ويعالجها. ويقلل ذلك من تكلفة التنسيق للمنتجات عالية التردد.
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: 10منتج أسطر الملف
اقرأ ملفًا بطريقة كسولة: يقرأ كوروتين المنتج الأسطر واحدًا تلو الآخر وينفذ yield لكل سطر. ويعالج المستهلك الأسطر من دون تحميل الملف بأكمله إلى الذاكرة.
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)مرحلة التحويل
أدرج مرحلة تحويل بين المنتج والمستهلك. تقرأ مرحلة التحويل من كوروتين واحد وتنفذ yield للقيم المعالجة إلى كوروتين آخر. وابنِ خطوط أنابيب للبيانات عبر ربط هذه المراحل.
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 12انتشار الأخطاء في خطوط الأنابيب
تنتشر الأخطاء في خطوط أنابيب الكوروتينات عبر الحالة المنتهية أو باستخدام pcall. غلّف مراحل خط الأنابيب داخل pcall لالتقاط الأخطاء ومعالجتها بسلاسة من دون تعطيل خط الأنابيب بأكمله.
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) endدمج المنتجات
ادمج عدة منتجات في منتج واحد: تناوب بينها جميعًا ما دامت حية، وأعد كل عنصر بالتتابع. وتوقف عندما تنفد جميع المنتجات.
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 6حالة استخدام واقعية
خط أنابيب لمعالجة السجلات: يقرأ المنتج أسطر السجل، وتحتفظ مرحلة التصفية بأسطر الأخطاء فقط، وتستخرج مرحلة التحويل المعلومات الأساسية، ثم يجمع المستهلك البيانات حسب نوع الخطأ. وكل مرحلة كوروتين مستقل قابل للاختبار.
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 failedاختبار سريع
كيف يتعامل نمط المنتج والمستهلك باستخدام الكوروتينات مع الضغط العكسي؟
مراجعة: المنتج والمستهلك
الملخص:
- ينفذ المنتج yield للعناصر؛ ويقود المستهلك العملية باستدعاء resume
- المنتجات اللانهائية:
while true do yield() end - خطوط الأنابيب: اربط كوروتينات التحويل بين المنتج والمستهلك
- الضغط العكسي تلقائي: ينتظر المنتج المستهلك
- مراحل الدفعات والتصفية والدمج بوصفها أغلفة للكوروتينات
- استخدم pcall في مراحل خط الأنابيب لعزل الأخطاء
الأسئلة الشائعة
هل درس «نمط المنتج والمستهلك» مجاني؟
نعم — نص درس «نمط المنتج والمستهلك» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Lua Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Lua Academy 4 دروس في المجموع.
ماذا ستتعلم في «نمط المنتج والمستهلك»؟
نفّذ خط أنابيب المنتج والمستهلك باستخدام البرامج التعاونية تتمرن على Lua Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Lua Academy؟
لا تُشترط خبرة سابقة. Lua Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «نمط المنتج والمستهلك»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Lua Academy هذا؟
نعم. كل درس في Lua Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- إنشاء البرامج التعاونية
- resume وyield
- حالة البرنامج التعاوني
- نمط المنتج والمستهلك