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
posted @ 2021-09-07 00:39  胡勇健  阅读(2137)  评论(0编辑  收藏  举报