lua協程的運用

    生產者與消費者,看下例: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

相關文章
相關標籤/搜索