<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 15 Lua 協同程序\(coroutine\) ## 什么是協程\(coroutine\)? > (1)線程 首先復習一下多線程。我們都知道線程——Thread。每一個線程都代表一個執行序列。 當我們在程序中創建多線程的時候,看起來,同一時刻多個線程是同時執行的,不過實質上多個線程是并發的,因為只有一個CPU,所以實質上同一個時刻只有一個線程在執行。 在一個時間片內執行哪個線程是不確定的,我們可以控制線程的優先級,不過真正的線程調度由CPU的調度決定。 > (2)協程 那什么是協程呢?協程跟線程都代表一個執行序列。不同的是,協程把線程中不確定的地方盡可能的去掉,執行序列間的切換不再由CPU隱藏的進行,而是由程序顯式的進行。 所以,使用協程實現并發,需要多個協程彼此協作。 ### 基本語法 | 方法 | 描述 | | :--- | :--- | | coroutine.create\(\) | 創建coroutine,返回coroutine, 參數是一個函數,當和resume配合使用的時候就喚醒函數調用 | | coroutine.resume\(\) | 重啟coroutine,和create配合使用 | | coroutine.yield\(\) | 掛起coroutine,將coroutine設置為掛起狀態,這個和resume配合使用能有很多有用的效果 | | coroutine.status\(\) | 查看coroutine的狀態 注:coroutine的狀態有三種:dead,suspend,running,具體什么時候有這樣的狀態請參考下面的程序 | | coroutine.wrap() | 創建coroutine,返回一個函數,一旦你調用這個函數,就進入coroutine,和create功能重復 | | coroutine.running\(\) | 返回正在跑的coroutine,一個coroutine就是一個線程,當使用running的時候,就是返回一個corouting的線程號 | ### ### **三、coroutine庫詳解** > \(1\)coroutine.create \(f\) 傳一個函數參數,用來創建協程。返回一個“thread”對象。 > \(2\)coroutine.isyieldable \(\) 如果正在運行的協程可以讓出,則返回真。值得注意的是,只有主協程(線程)和C函數中是無法讓出的。 > \(3\)coroutine.resume \(co \[, val1, ···\]\) 這是一個非常重要的函數。用來啟動或再次啟動一個協程,使其由掛起狀態變成運行狀態。 可以這么說,resume函數相當于在執行協程中的方法。參數Val1...是執行協程co時傳遞給協程的方法。 #### **首次執行協程co時,參數Val1...會傳遞給協程co的函數;** #### **再次執行協程co時,參數Val1...會作為給協程co中上一次yeild的返回值。** 不知道這句話大家理解了沒,這是協程的核心。如果沒理解也不用急,繼續往下看,稍后我會詳細解釋。 resume函數返回什么呢?有3種情況: 1)、如果協程co的函數執行完畢,協程正常終止,`resume` 返回 true和函數的返回值。 2)、如果協程co的函數執行過程中,協程讓出了(調用了yeild\(\)方法),那么resume返回true和協程中調用yeild傳入的參數。 3)、如果協程co的函數執行過程中發生錯誤,resume返回false與錯誤消息。 可以看到resume無論如何都不會導致程序崩潰。它是在保護模式下執行的。 > \(4\)coroutine.running \(\) 用來判斷當前執行的協程是不是主線程,如果是,就返回true。 > \(5\)coroutine.status \(co\) 返回一個字符串,表示協程的狀態。有4種狀態: 1)、running。如果在協程的函數中調用status,傳入協程自身的句柄,那么執行到這里的時候才會返回running狀態。 2)、suspended。如果協程還未結束,即自身調用了yeild或還沒開始運行,那么就是suspended狀態。 3)、normal。如果協程A resume 協程B時,協程A處于的狀態為normal。在協程B的執行過程中,協程A就一直處于normal狀態。因為它這時候既不是掛起狀態、也不是運行狀態。 4)、dead。如果一個協程發生錯誤結束,或正常終止。那么就處于dead狀態。如果這時候對它調用resume,將返回false和錯誤消息。 > \(6\)coroutine.wrap \(f\) wrap\(\)也是用來創建協程的。只不過這個協程的句柄是隱藏的。跟create\(\)的區別在于: 1)、wrap\(\)返回的是一個函數,每次調用這個函數相當于調用coroutine.resume\(\)。 2)、調用這個函數相當于在執行resume\(\)函數。 3)、調用這個函數時傳入的參數,就相當于在調用resume時傳入的除協程的句柄外的其他參數。 4)、調用這個函數時,跟resume不同的是,它并不是在保護模式下執行的,若執行崩潰會直接向外拋出。 > \(7\)coroutine.yield \(···\) 使正在執行的函數掛起。 **  傳遞給yeild的參數會作為resume的額外返回值。** **   同時,如果對該協程不是第一次執行resume,resume函數傳入的參數將會作為yield的返回值。** ### 以下實例演示了以上各個方法的用法: 例子1:簡單實用resume、yield,如下: ```lua --創建一個協程coco coco = coroutine.create( function (a, b) print ("resume args:"..a..","..b) --協程被掛起 yreturn = coroutine.yield() -- yreturn 應該是下次resume喚醒傳遞進來的參數 print ("yretur:"..yreturn) end) --第一次啟動coco協程 print (coroutine.resume(coco,0,1)) --第二次啟動coco協程 print (coroutine.resume(coco, "第二次傳遞的參數,作為上一次yield的返回值")) ``` 輸出結果為: ```lua resume args:0,1 true yretur:第二次傳遞的參數,作為上一次yield的返回值 true ``` 例子2:簡單使用wrap,如下: ```lua coco2 = coroutine.wrap(function (a, b) print ("warp resume args:"..a..","..b) yreturn = coroutine.yield() print ("continue "..yreturn) end) print (type(coco2)) coco2(0,1) coco2(3) ``` 輸出結果: ```lua function warp resume args:0,1 continue 3 ``` 例子3:多個協程配合使用 ```lua function status() print("Co1's status:"..coroutine.status(co1)..",".."co2's status:"..coroutine.status(co2)) end co1 = coroutine.create(function (a) print ("arg is :"..a) status() local stat, rere = coroutine.resume(co2, "2") print ("resume's return is "..rere) status() local stat2,rere2 = coroutine.resume(co2, "4") print ("resume's return is"..rere2) local arg = coroutine.yield("6") end) co2 = coroutine.create(function (a) print ("arg is :"..a) status() local rey = coroutine.yield("3") print ("yeild's return is ".. rey) status() coroutine.yield("5") end) stat,main_ret = coroutine.resume(co1, "1") status() print ("last return is "..main_ret) ``` 結果如下: ```lua arg is :1 Co1's status:running,co2's status:suspended arg is :2 Co1's status:normal,co2's status:running resume's return is 3 Co1's status:running,co2's status:suspended yeild's return is 4 Co1's status:normal,co2's status:running resume's return is5 Co1's status:suspended,co2's status:suspended last return is 6 ``` 例子4:多個協程配合使用 ```lua function foo(a) print ("foo", a) return coroutine.yield(2*a) end co = coroutine.create(function(a, b) print("co-body", a, b) local r = foo(a+1) print("co-body", r) local r, s = coroutine.yield(a+b, a-b) print ("co-body", r, s) return b, "end" end) ``` ```lua co-body 1 10 foo 2 main true 4 co-body r main true 11 -9 co-body x y main true 10 end main false cannot resume dead coroutine ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看