hyperf 協程理解和使用


協程是一種輕量級的線程,由用戶代碼來調度和管理,而不是由操作系統內核來進行調度,也就是在用戶態進行

創建協程方法

co函數
public function test(){
    echo "first id: ". Coroutine::id().PHP_EOL;
    co(function () {
        echo "second id: ". Coroutine::id().PHP_EOL;
        echo "這是co方法產生的協程".PHP_EOL;
    });
}

訪問/index/test

http://ip:9501/index/test

終端顯示結果

first id: 2
second id: 3
這是co方法產生的協程
go函數
public function test(){
    echo "first id: ". Coroutine::id().PHP_EOL;
    go(function () {
        echo "second id: ". Coroutine::id().PHP_EOL;
        echo "這是go方法產生的協程".PHP_EOL;
    });
}

訪問/index/test

http://ip:9501/index/test

終端顯示結果

first id: 2
second id: 3
這是go方法產生的協程

Coroutine::create方法

use Hyperf\Utils\Coroutine;

public function test(){
    echo "first id: ". Coroutine::id().PHP_EOL;
    Coroutine::create(function(){
        echo "second id: ". Coroutine::id().PHP_EOL;
        echo "這是coroutine::create方法產生的協程".PHP_EOL;
    });
}

訪問/index/test

http://ip:9501/index/test

終端顯示結果

first id: 2
second id: 3
這是coroutine::create方法產生的協程

協程相關方法

判斷當前是否處於協程環境(Hyperf\Utils\Coroutine::inCoroutine(): bool)

Hyperf\Utils\Coroutine::inCoroutine(): bool

獲取當前協程id

Hyperf\Utils\Coroutine::id()

channel通道

Channel 主要用於協程間通訊

public function test(){
    co(function () {
        $channel = new \Swoole\Coroutine\Channel();
        co(function () use ($channel) {
            $channel->push('子協程的數據');
        });
        $data = $channel->pop();
        echo "獲取子協程數據: ".$data;
    });
}

訪問/index/test

http://ip:9501/index/test
獲取子協程數據: 子協程的數據

defer特性

public function test(){
    Coroutine::defer(function(){
        echo "第一個defer".PHP_EOL;
    });
    Coroutine::defer(function(){
        echo "第二個defer".PHP_EOL;
    });
    Coroutine::defer(function(){
        echo "第三個defer".PHP_EOL;
    });
    echo 'defer test'.PHP_EOL;
}

訪問/index/test

http://ip:9501/index/test

終端結果顯示

defer test
第三個defer
第二個defer
第一個defer

WaitGroup特性

public function test(){
    $wg = new \Hyperf\Utils\WaitGroup();
    // 計數器加二
    $wg->add(2);
    // 創建協程 A
    co(function () use ($wg) {
           mt_srand();
           $time = mt_rand(1, 5);
           sleep($time);
           // some code
           echo "協程A執行完成".PHP_EOL;
           //計算器減一
           $wg->done();
    });
    // 創建協程 B
    co(function () use ($wg) {
           mt_srand();
           $time = mt_rand(1, 5);
           sleep($time);
           // some code
           echo "協程B執行完成".PHP_EOL;
           // 計數器減一
           $wg->done();
    });
    // 等待協程 A 和協程 B 運行完成
    $wg->wait();
    echo "全部程序執行完成".PHP_EOL;
}

訪問/index/test

http://ip:9501/index/test

終端結果顯示

協程B執行完成
協程A執行完成
全部程序執行完成

Parallel特性

use Hyperf\Utils\Exception\ParallelExecutionException;
use Hyperf\Utils\Coroutine;
use Hyperf\Utils\Parallel;


public function test(){
    $parallel = new Parallel();
    $parallel->add(function () {
        mt_srand();
        $time = mt_rand(1, 5);
        sleep($time);
        echo "協程A執行完成".PHP_EOL;
        return Coroutine::id();
    });
    $parallel->add(function () {
        mt_srand();
        $time = mt_rand(1, 5);
        sleep($time);
        echo "協程B執行完成".PHP_EOL;
        return Coroutine::id();
    });

    try{
        // $results 結果為 [1, 2]
        $results = $parallel->wait();
        echo "results:".PHP_EOL;
        var_dump($results);
    } catch(ParallelExecutionException $e){
        // $e->getResults() 獲取協程中的返回值。
        // $e->getThrowables() 獲取協程中出現的異常。
        var_dump($e->getResults());
    }

}

訪問/index/test

http://ip:9501/index/test

終端結果顯示

協程B執行完成
協程A執行完成
results:
array(2) {
  [1]=>
  int(4)
  [0]=>
  int(3)
}

簡寫版

$results = parallel([
    function () {
        mt_srand();
        $time = mt_rand(1, 5);
        sleep($time);
        echo "協程A執行完成".PHP_EOL;
        return Coroutine::id();
    },
    function () {
        mt_srand();
        $time = mt_rand(1, 5);
        sleep($time);
        echo "協程B執行完成".PHP_EOL;
        return Coroutine::id();
    }
]);

協程上下文

public function test(){
    co(function(){
        Context::set('name','huyongjian');
        $name = Context::get('name');
        echo $name.PHP_EOL;
    });
}

訪問/index/test

http://ip:9501/index/test

終端結果顯示

huyongjian


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM