先看一段代碼
coAA = coroutine.create(
function ()
print('at coAA -- 1')
--這里啟動協(xié)程coBB
coroutine.resume(coBB)
print('at coAA -- 2')
end
)
coBB = coroutine.create(
function ()
print('at coBB -- 1')
print('at coBB -- 2')
--這里啟動協(xié)程coCC
coroutine.resume(coCC)
print('at coBB -- 3')
end
)
coCC = coroutine.create(
function ()
print('at coCC -- 1')
--這里掛起協(xié)程coCC
coroutine.yield()
print('at coCC -- 2')
end
)
--這里啟動協(xié)程coA
coroutine.resume(coAA)
運行結(jié)果
at coAA -- 1
at coBB -- 1
at coBB -- 2
at coCC -- 1
at coBB -- 3
at coAA -- 2
因為coCC被掛起,所以壶谒,沒有輸出
at coCC -- 2
可以調(diào)用coroutine.resume(coCC)云矫,觸發(fā)掛起的協(xié)程
上面代碼中主要用到coroutine的API
coroutine.create (f) --創(chuàng)建一個協(xié)程
coroutine.resume (co [, val1, ···]) --觸發(fā)一個協(xié)程
coroutine.yield (···) --掛起(阻塞)一個協(xié)程
具體解釋如下
coroutine庫詳解
(1)coroutine.create (f)
傳一個函數(shù)參數(shù),用來創(chuàng)建協(xié)程汗菜。返回一個“thread”對象让禀。
(2)coroutine.isyieldable ()
如果正在運行的協(xié)程可以讓出,則返回真陨界。值得注意的是巡揍,只有主協(xié)程(線程)和C函數(shù)中是無法讓出的。
(3)coroutine.resume (co [, val1, ···])
這是一個非常重要的函數(shù)菌瘪。用來啟動或再次啟動一個協(xié)程腮敌,使其由掛起狀態(tài)變成運行狀態(tài)。
可以這么說麻车,resume函數(shù)相當(dāng)于在執(zhí)行協(xié)程中的方法缀皱。參數(shù)Val1...是執(zhí)行協(xié)程co時傳遞給協(xié)程的方法。
首次執(zhí)行協(xié)程co時动猬,參數(shù)Val1...會傳遞給協(xié)程co的函數(shù);
再次執(zhí)行協(xié)程co時表箭,參數(shù)Val1...會作為給協(xié)程co中上一次yeild的返回值赁咙。
不知道這句話大家理解了沒,這是協(xié)程的核心。如果沒理解也不用急彼水,繼續(xù)往下看崔拥,稍后我會詳細解釋。
resume函數(shù)返回什么呢凤覆?有3種情況:
1)链瓦、如果協(xié)程co的函數(shù)執(zhí)行完畢,協(xié)程正常終止盯桦,resume 返回 true和函數(shù)的返回值慈俯。
2)、如果協(xié)程co的函數(shù)執(zhí)行過程中拥峦,協(xié)程讓出了(調(diào)用了yeild()方法)贴膘,那么resume返回true和協(xié)程中調(diào)用yeild傳入的參數(shù)。
3)略号、如果協(xié)程co的函數(shù)執(zhí)行過程中發(fā)生錯誤刑峡,resume返回false與錯誤消息。
可以看到resume無論如何都不會導(dǎo)致程序崩潰玄柠。它是在保護模式下執(zhí)行的突梦。
(4)coroutine.running ()
用來判斷當(dāng)前執(zhí)行的協(xié)程是不是主線程,如果是羽利,就返回true阳似。
(5)coroutine.status (co)
返回一個字符串,表示協(xié)程的狀態(tài)铐伴。有4種狀態(tài):
1)撮奏、running。如果在協(xié)程的函數(shù)中調(diào)用status当宴,傳入?yún)f(xié)程自身的句柄畜吊,那么執(zhí)行到這里的時候才會返回running狀態(tài)。
2)户矢、suspended玲献。如果協(xié)程還未結(jié)束,即自身調(diào)用了yeild或還沒開始運行梯浪,那么就是suspended狀態(tài)捌年。
3)、normal挂洛。如果協(xié)程Aresume協(xié)程B時礼预,協(xié)程A處于的狀態(tài)為normal。在協(xié)程B的執(zhí)行過程中虏劲,協(xié)程A就一直處于normal狀態(tài)托酸。因為它這時候既不是掛起狀態(tài)褒颈、也不是運行狀態(tài)。
4)励堡、dead谷丸。如果一個協(xié)程發(fā)生錯誤結(jié)束,或正常終止应结。那么就處于dead狀態(tài)刨疼。如果這時候?qū)λ{(diào)用resume,將返回false和錯誤消息鹅龄。
(6)coroutine.wrap (f)
wrap()也是用來創(chuàng)建協(xié)程的揩慕。只不過這個協(xié)程的句柄是隱藏的。跟create()的區(qū)別在于:
1)砾层、wrap()返回的是一個函數(shù)漩绵,每次調(diào)用這個函數(shù)相當(dāng)于調(diào)用coroutine.resume()。
2)肛炮、調(diào)用這個函數(shù)相當(dāng)于在執(zhí)行resume()函數(shù)止吐。
3)、調(diào)用這個函數(shù)時傳入的參數(shù)侨糟,就相當(dāng)于在調(diào)用resume時傳入的除協(xié)程的句柄外的其他參數(shù)碍扔。
4)、調(diào)用這個函數(shù)時秕重,跟resume不同的是不同,它并不是在保護模式下執(zhí)行的,若執(zhí)行崩潰會直接向外拋出溶耘。
(7)coroutine.yield (···)
使正在執(zhí)行的函數(shù)掛起二拐。
傳遞給yeild的參數(shù)會作為resume的額外返回值。
同時凳兵,如果對該協(xié)程不是第一次執(zhí)行resume百新,resume函數(shù)傳入的參數(shù)將會作為yield的返回值。