<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 協程:Go + Chan + Defer [TOC] `Swoole4`為`PHP`語言提供了強大的`CSP`協程編程模式。底層提供了`3`個關鍵詞,可以方便地實現各類功能。 * `Swoole4`提供的`PHP協程`語法借鑒自`Golang`,在此向`GO`開發組致敬 * `PHP+Swoole`協程可以與`Golang`很好地互補。`Golang`:靜態語言,嚴謹強大性能好,`PHP+Swoole`:動態語言,靈活簡單易用 > 本文基于`Swoole-4.2.9`和`PHP-7.2.9`版本 # 關鍵詞 * `go`:創建一個協程 * `chan`:創建一個通道 * `defer`:延遲任務,在協程退出時執行,先進后出 這`3`個功能底層現全部為**內存操作**,沒有任何`IO`資源消耗。就像`PHP`的`Array`一樣是非常廉價的。如果有需要就可以直接使用。這與`socket`和`file`操作不同,后者需要向操作系統申請端口和文件描述符,讀寫可能會產生阻塞的`IO`等待。 # 協程并發 使用`go`函數可以讓一個函數并發地去執行。在編程過程中,如果某一段邏輯可以并發執行,就可以將它放置到`go`協程中執行。 ## 順序執行 ~~~ function test1() { sleep(1); echo "b"; } function test2() { sleep(2); echo "c"; } test1(); test2(); ~~~ #### 執行結果: ~~~ htf@LAPTOP-0K15EFQI:~$ time php b1.php bc real 0m3.080s user 0m0.016s sys 0m0.063s htf@LAPTOP-0K15EFQI:~$ ~~~ 上述代碼中,`test1`和`test2`會順序執行,需要`3`秒才能執行完成。 ## 并發執行 使用`go`創建協程,可以讓`test1`和`test2`兩個函數變成并發執行。 ~~~ Swoole\Runtime::enableCoroutine(); go(function () { sleep(1); echo "b"; }); go(function () { sleep(2); echo "c"; }); ~~~ > `Swoole\Runtime::enableCoroutine()`作用是將`PHP`提供的`stream`、`sleep`、`pdo`、`mysqli`、`redis`等功能從同步阻塞切換為協程的異步`IO` #### 執行結果: ~~~ bchtf@LAPTOP-0K15EFQI:~$ time php co.php bc real 0m2.076s user 0m0.000s sys 0m0.078s htf@LAPTOP-0K15EFQI:~$ ~~~ 可以看到這里只用了`2`秒就執行完成了。 * 順序執行耗時等于所有任務執行耗時的總和 :`t1+t2+t3...` * 并發執行耗時等于所有任務執行耗時的最大值 :`max(t1, t2, t3, ...)` # 協程通信 有了`go`關鍵詞之后,并發編程就簡單多了。與此同時又帶來了新問題,如果有`2`個協程并發執行,另外一個協程,需要依賴這兩個協程的執行結果,如果解決此問題呢? 答案就是使用通道(`Channel`),在`Swoole4`協程中使用`new chan`就可以創建一個通道。通道可以理解為自帶協程調度的隊列。它有兩個接口`push`和`pop`: * `push`:向通道中寫入內容,如果已滿,它會進入等待狀態,有空間時自動恢復 * `pop`:從通道中讀取內容,如果為空,它會進入等待狀態,有數據時自動恢復 使用通道可以很方便地實現**并發管理**。 ~~~ $chan = new chan(2); # 協程1 go (function () use ($chan) { $result = []; for ($i = 0; $i < 2; $i++) { $result += $chan->pop(); } var_dump($result); }); # 協程2 go(function () use ($chan) { $cli = new Swoole\Coroutine\Http\Client('www.qq.com', 80); $cli->set(['timeout' => 10]); $cli->setHeaders([ 'Host' => "www.qq.com", "User-Agent" => 'Chrome/49.0.2587.3', 'Accept' => 'text/html,application/xhtml+xml,application/xml', 'Accept-Encoding' => 'gzip', ]); $ret = $cli->get('/'); // $cli->body 響應內容過大,這里用 Http 狀態碼作為測試 $chan->push(['www.qq.com' => $cli->statusCode]); }); # 協程3 go(function () use ($chan) { $cli = new Swoole\Coroutine\Http\Client('www.163.com', 80); $cli->set(['timeout' => 10]); $cli->setHeaders([ 'Host' => "www.163.com", "User-Agent" => 'Chrome/49.0.2587.3', 'Accept' => 'text/html,application/xhtml+xml,application/xml', 'Accept-Encoding' => 'gzip', ]); $ret = $cli->get('/'); // $cli->body 響應內容過大,這里用 Http 狀態碼作為測試 $chan->push(['www.163.com' => $cli->statusCode]); }); ~~~ #### 執行結果: ~~~ htf@LAPTOP-0K15EFQI:~/swoole-src/examples/5.0$ time php co2.php array(2) { ["www.qq.com"]=> int(302) ["www.163.com"]=> int(200) } real 0m0.268s user 0m0.016s sys 0m0.109s htf@LAPTOP-0K15EFQI:~/swoole-src/examples/5.0$ ~~~ 這里使用`go`創建了`3`個協程,協程`2`和協程`3`分別請求`qq.com`和`163.com`主頁。協程`1`需要拿到`Http`請求的結果。這里使用了`chan`來實現并發管理。 * 協程`1`循環兩次對通道進行`pop`,因為隊列為空,它會進入等待狀態 * 協程`2`和協程`3`執行完成后,會`push`數據,協程`1`拿到了結果,繼續向下執行 # 延遲任務 在協程編程中,可能需要在協程退出時自動執行一些任務,做清理工作。類似于`PHP`的`register_shutdown_function`,在`Swoole4`中可以使用`defer`實現。 ~~~ Swoole\Runtime::enableCoroutine(); go(function () { echo "a"; defer(function () { echo "~a"; }); echo "b"; defer(function () { echo "~b"; }); sleep(1); echo "c"; }); ~~~ #### 執行結果: ~~~ htf@LAPTOP-0K15EFQI:~/swoole-src/examples/5.0$ time php defer.php abc~b~a real 0m1.068s user 0m0.016s sys 0m0.047s htf@LAPTOP-0K15EFQI:~/swoole-src/examples/5.0$ ~~~ # 結語 `Swoole4`提供的`Go + Chan + Defer`為`PHP`帶來了一種全新的`CSP`并發編程模式。靈活使用`Swoole4`提供的各項特性,可以解決工作中各類復雜功能的設計和開發。
                  <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>

                              哎呀哎呀视频在线观看