swoole的協程channel容量理解和實例說明

首先翻到官網https://wiki.swoole.com/#/coroutine/channelphp

有關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的做用是限制管道寫入的長度。

相關文章
相關標籤/搜索