生產者與消費者,看下例:cookie
local function producer() return coroutine.create( function(cookie) print("cookie = ",cookie) local t = {1,2,3} for i = 1,#t do cookie = coroutine.yield(t[i] + cookie) --cookie是consumer傳回來的返回值 print('producer cookie',cookie) end print("******") end ) end function consumer(prod) local cookie = 10 while true do --cookie是producer coroutine.yield的返回值,cookie做爲producer的返回值設置給cookie local running ,producer = coroutine.resume(prod, cookie) if running == false then return else print('running:',running,',producer:',producer,',cookie:',cookie) cookie = cookie*cookie end end end consumer(producer())
輸出:異步
cookie = 10 running: true ,producer: 11 ,cookie: 10 producer cookie 100 running: true ,producer: 102 ,cookie: 100 producer cookie 10000 running: true ,producer: 10003 ,cookie: 10000 producer cookie 100000000 ****** running: true ,producer: nil ,cookie: 100000000
由輸出咱們能夠知道,print("cookie = ",cookie)在producer協程第一次運行的時候被調用一次,接着進入for循環,剛進for循環的時候,producer就被掛起,這是yield會返回兩個值給resume,第一個值若是爲true則表示沒有錯誤,不然則爲發生了錯誤,第二個參數則是yield傳入的參數,這裏是:t[i] + cookie,第一次的時候,返回爲true,11.接着因爲consumer協程是會一直resume生產者(producer)協程的,知道返回非true爲止。函數
上面的程序大體意思是:消費者剛剛開始的時候,想要10個餅乾,而後他告訴生產者,生產者接收到消費者想要本身生產的餅乾數量後開始生產,生產到比消費者想要的餅乾數量加t[i](i爲第幾回生產)時,中止生產,並告訴消費者,我已經生產了的餅乾數量。而後消費者開始使用這些餅乾,而後消費者以爲餅乾至關好吃,而後每次都以上一個的平方的數量讓生產者生產餅乾。在生產到第四次的時候,生產者不在生產餅乾了,並通知消費者(多是因爲生產數量過大,而消費者不願事先給訂金而致使的)
lua
咱們也可使用協程去替代回調函數。這是我在一個項目中遇到的一個問題,在戰鬥中,咱們每每但願英雄在執行完某一步驟的時候,執行某一個方法,這時候大部分人都會選擇回調函數來實現,可是在一個戰鬥系統中,會存在屢次回調的狀況,雖然回調函數也能夠實現可是可讀性就相對較差。好比咱們想要英雄走到npc身邊,而後諮詢npc,接着npc回覆,咱們先用回調來實現一下:spa
hero.walk(function() hero.say(function() npc.say("...") end,"我帥嗎?") end,npc)
接着咱們使用協同程序來實現:線程
function dothing(func,...) --返回正在進行的線程,在主線程調用將返回nil local current = coroutine.running() func(function() coroutine.resume(current) end,...) coroutine.yield() end coroutine.create(function() dothing(hero.walk,npc) dothing(hero.say,"我帥嗎?") npc.say("...") end) coroutine.resume(co)
一旦一個異步函數被調用,協程就會使用coroutine.yield()方法將該協程暫時懸掛起來,在相應的回調函數中加上coroutine.resume(current),使其返回目前正在執行的協程中。code