首先翻到官網https://wiki.swoole.com/#/coroutine/channel。php
有關channel:通道,用於協程間通信,支持多生產者協程和多消費者協程。底層自動實現了協程的切換和調度。swoole
其構造方法:Swoole\Coroutine\Channel->__construct(int $capacity = 1),有個capacity的容量參數,一開始並不理解, 敲點代碼嘗試下,理解起來容易許多。spa
[root@guangzhou coroutine]# cat coroutine_channel.php <?php #開啓一鍵協程 Co::set(['hook_flags'=> SWOOLE_HOOK_ALL]); Co\run(function(){ // 設置一個容量爲1的通道 $chan = new Swoole\Coroutine\Channel(1); Swoole\Coroutine::create(function () use ($chan) { for($i = 0; $i < 6; $i++) { $chan->push( date('H:i:s') . " 數據 i:" . $i . "\n"); echo date('H:i:s') . " 第{$i}次塞數據時間\n"; } }); Swoole\Coroutine::create(function () use ($chan) { while(1) { $data = $chan->pop(); if($data){ echo date('H:i:s') . " 取數據時間\n"; echo $data . "\n"; Co::sleep(2); }else{ break; } } }); });
//看到這段代碼,你認爲他的輸出狀況是怎樣,先本身思考下!!
上面腳本運行後每次pop後獲取通道數據後休眠2秒,是協程模式,可能也會想固然認爲每次取到數據的間隔應該是2秒??3d
如今運行腳本:code
[root@guangzhou coroutine]# php coroutine_channel.php 06:55:32 第0次塞數據時間 06:55:32 第1次塞數據時間 06:55:32 取數據時間 06:55:32 數據 i:0 06:55:34 第2次塞數據時間 06:55:34 取數據時間 06:55:32 數據 i:1 06:55:36 第3次塞數據時間 06:55:36 取數據時間 06:55:32 數據 i:2 06:55:38 第4次塞數據時間 06:55:38 取數據時間 06:55:34 數據 i:3 06:55:40 第5次塞數據時間 06:55:40 取數據時間 06:55:36 數據 i:4 06:55:42 取數據時間 06:55:38 數據 i:5
有沒有發現前三次取數據時間點都是2秒的,第四次的數據一會兒到了4秒。協程
通過swoole官方羣的高人指點,給出了正確的執行路徑以下圖(數字從小到大是執行順序):blog
由於設置的capacity=1,致使第二次的push未成功,須要先pop方能繼續下去。ci
第一次pop後,回到第三次push循環,程序判斷管道已滿這時將處理第一次pop的數據,又開始第四次push循環,程序判斷管道又滿了,pop第二次push的數據。get
到目前爲止前三次push的數據並未進入到sleep這裏,致使後續打印第一次pop數據時,塞數據時間點比取數據時間點被推後了。it
從第三次數據pop後的數據都要經歷push失敗->echo+sleep->pop上一次的,這裏就會有休眠2秒的時間加上pop上次時間就是4秒了。
這裏有點繞,須要多思考並動手實踐。
修改capacity=10,並push循環7次,運行程序:
[root@guangzhou coroutine]# cat coroutine_channel.php <?php #開啓一鍵協程 Co::set(['hook_flags'=> SWOOLE_HOOK_ALL]); Co\run(function(){ // 設置一個容量爲1的通道 $chan = new Swoole\Coroutine\Channel(10); Swoole\Coroutine::create(function () use ($chan) { for($i = 0; $i < 7; $i++) { $chan->push( date('H:i:s') . " 數據 i:" . $i . "\n"); echo date('H:i:s') . " 第{$i}次塞數據時間\n"; } }); Swoole\Coroutine::create(function () use ($chan) { while(1) { $data = $chan->pop(); if($data){ echo date('H:i:s') . " 取數據時間\n"; echo $data . "\n"; Co::sleep(2); }else{ break; } } }); });
執行腳本:
[root@guangzhou coroutine]# php coroutine_channel.php 07:29:22 第0次塞數據時間 07:29:22 第1次塞數據時間 07:29:22 第2次塞數據時間 07:29:22 第3次塞數據時間 07:29:22 第4次塞數據時間 07:29:22 第5次塞數據時間 07:29:22 第6次塞數據時間 07:29:22 取數據時間 07:29:22 數據 i:0 07:29:24 取數據時間 07:29:22 數據 i:1 07:29:26 取數據時間 07:29:22 數據 i:2 07:29:28 取數據時間 07:29:22 數據 i:3 07:29:30 取數據時間 07:29:22 數據 i:4 07:29:32 取數據時間 07:29:22 數據 i:5 07:29:34 取數據時間 07:29:22 數據 i:6
發現全部 i:xxx 的時間點幾乎一致。
如今得出結論capacity的做用是限制管道寫入的長度。