哎。週五晚上我都還這麼努力看書。真是好孩子。(小若:不想吐槽了)php
事實上我都準備玩遊戲看電影去的了。但是這書就擺在桌子上。而且正對着我,就想着。掃兩眼吧。多線程
結果一掃就不正確勁了,因爲這內容有點繞,有點小混亂,假設我現在不記錄下來的話。下週一可能又要又一次看一次了。ide
好吧,今天咱們來聊聊協同程序。函數
笨木頭花心貢獻,哈?花心?不,是用心~post
轉載請註明,原文地址: http://www.benmutou.com/archives/1733ui
文章來源:笨木頭與遊戲開發lua
你們都知道線程吧?都知道多線程吧?協同程序就和這線程差點兒相同,但是又有比較明顯的區別。url
多個協同程序在隨意時刻僅僅能運行一個,儘管線程在某種意義上也是這樣,但這不是同樣的概念。spa
換句話說,一個協同程序在運行的時候。其它協同程序是沒法得到運行的機會的。線程
僅僅有正在運行的協同程序主動掛起時,其它協同程序纔有機會運行。
而線程呢?即便不主動休眠。也很是有可能因爲輪片時間到達而把運行機會讓給其它線程。
建立協同程序很是easy。咋一看。事實上和線程沒區別~
代碼例如如下:
協同的程序的操做都在coroutine裏,create函數的參數就是協同程序要運行的函數,就這麼運行代碼是沒有效果的。
因爲協同程序建立後,默認是掛起狀態。
協同程序的四種狀態分別爲:掛起(suspended)、運行(running)、死亡(dead)、正常(normal)。
要想協同程序運行起來,就要調用resume函數。
例如如下代碼:
輸出結果例如如下:
[LUA-print] hello coroutine
剛剛那個協同程序太簡陋的。沒有不論什麼做用,直接打印一條語句以後就結束了,同一時候它的狀態也變成了死亡狀態。
咱們來一個帥一點的協同程序:
運行結果例如如下:
[LUA-print] 木頭挺聰明的+1
[LUA-print] 木頭挺聰明的+2
因此我就說,電腦就是誠實。這日誌打印的,真好看(小若:咱們不要理這個神經病了)
既然協同程序和線程差點兒相同。那確定不能讓協同程序一次過運行完成了,這就沒有意義了。
咱們來看看怎麼讓協同程序掛起,例如如下代碼:
輸出結果例如如下:
[LUA-print] 木頭挺聰明的+1
[LUA-print] suspended
這回就僅僅輸出了一條日誌就中止了,後面咱們還調用了status函數,打印協同程序當前的狀態,suspended即爲掛起狀態。
因爲這個協同程序尚未運行完成。因此僅僅能是掛起狀態。
那麼,假設讓這協同程序繼續運行呢?很是easy,再次調用resume函數。如代碼:
此次有點複雜了。先看看輸出結果:
[LUA-print] 木頭挺聰明的+1
[LUA-print] suspended
[LUA-print] 木頭挺聰明的+2
[LUA-print] suspended
[LUA-print] dead
我一共運行了三次resume函數。但很是顯然,這個協同程序的for循環僅僅會運行2次。
那爲何第二次resume運行以後,協同程序的狀態仍是掛起呢?不該該是結束了麼?結束了就應該是死亡狀態了。
而第三次運行resume以後,反而沒有不論什麼輸出,此時的狀態才真正切換到死亡狀態。
這是爲何呢?(小若:趕忙說,不說我看電影去了)
再來這麼看看就明確了。加幾條打印代碼:
輸出結果例如如下:
[LUA-print] 木頭挺聰明的+1
[LUA-print] suspended
[LUA-print] 一次循環結束
[LUA-print] 木頭挺聰明的+2
[LUA-print] suspended
[LUA-print] 一次循環結束
[LUA-print] 協同程序結束
[LUA-print] dead
這就很是明顯了,在協同程序裏調用yield函數時。會被掛起,而yield函數的返回要等下一次調用resume函數時才幹獲得。
因此,yield函數如下的print語句在下一次的resume調用時才被運行。
又因此,當for循環第二次運行時,協同程序被掛起,需要等待再一次resume時。for循環才幹真正運行完成。
這就是這段代碼的特殊之處了。
事實上resume函數是有返回值的。
咱們試試運行如下的代碼:
輸出結果例如如下:
[LUA-print] true
[LUA-print] nil
resume返回兩個值,第一個值表明協同程序是否正常運行。第二個返回值天然是表明錯誤信息。
咱們試試讓協同程序出現錯誤:
輸出結果例如如下:
[LUA-print] false
[LUA-print] [string "src/main.lua"]:91: 呵呵。報錯了吧
好了,儘管我已經寫了這麼多了,但是我真正想記錄的東西還沒開始寫呢~!
我了個噗,今晚我還能不能好好玩了…
好吧,內容有點多,下一篇繼續…