6. 协程

协程是一种轻量级的线程,由用户代码来调度和管理,而不是由操作系统内核来进行调度,也就是在用户态进。

一、 创建协程

co(callable $callable)【推荐】
go(callable $callable)
Hyperf\Coroutine\Coroutine::create(callable $callable)

二、使用协程【数据共享的三种方式】

1. Channel通道

<?php

namespace App\Controller;

use Hyperf\Di\Annotation\Inject;
use Hyperf\Guzzle\ClientFactory;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Contract\RequestInterface;

use Swoole\Coroutine\Channel;
use function Hyperf\Coroutine\co;

#[AutoController]
class CoTestController
{
    #[Inject]
    private ClientFactory $client;
	
    // 延时接口(模拟I/O操作)
    public function sleep(RequestInterface $request)
    {
        $seconds = $request->query('seconds', 1);
        sleep($seconds);
        return $seconds;
    }

    public function test()
    {
        $channel = new Channel();	// 通过Channel通道 实现 协程间数据共享
        co(function () use($channel) {
            $client = $this->client->create();
            $client->get('127.0.0.1:9501/co_test/sleep?seconds=2');
            $channel->push(111);
        });
        co(function () use($channel) {
            $client = $this->client->create();
            $client->get('127.0.0.1:9501/co_test/sleep?seconds=2');
            $channel->push(222);
        });
        $result[] = $channel->pop();
        $result[] = $channel->pop();
        return $result;
    }
}

2. WaitGroup

<?php

namespace App\Controller;

use Hyperf\Coroutine\WaitGroup;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Guzzle\ClientFactory;
use Hyperf\HttpServer\Annotation\AutoController;
use function Hyperf\Coroutine\co;

#[AutoController]
class WaitGroupTestController
{
    #[Inject]
    private ClientFactory $client;

    public function test()
    {
        $wg = new WaitGroup();
        $result = [];
        $wg->add(2);    // 计数器加2,与开启的协程数相同
        co(function () use($wg, &$result) {
            $client = $this->client->create();
            $client->get('127.0.0.1:9501/co_test/sleep?seconds=2');
            $result[] = 111;
            $wg->done();    // 计数器减1
        });
        co(function () use($wg, &$result) {
            $client = $this->client->create();
            $client->get('127.0.0.1:9501/co_test/sleep?seconds=2');
            $result[] = 222;
            $wg->done();    // 计数器减1
        });
        $wg->wait();    // 等待协程 1 和协程 2 运行完成
        return $result;
    }
}

3. Parallel

<?php

namespace App\Controller;

use Hyperf\Coroutine\Parallel;
use Hyperf\Coroutine\WaitGroup;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Guzzle\ClientFactory;
use Hyperf\HttpServer\Annotation\AutoController;
use function Hyperf\Coroutine\co;

#[AutoController]
class ParallelTestController
{
    #[Inject]
    private ClientFactory $client;

    public function test()
    {
        $parallel = new Parallel();
        $parallel->add(function () {
            $client = $this->client->create();
            $client->get('127.0.0.1:9501/co_test/sleep?seconds=2');
            return 111;
        }, 'foo');  // add方法的第2个参数为 返回值的索引,可选
        $parallel->add(function () {
            $client = $this->client->create();
            $client->get('127.0.0.1:9501/co_test/sleep?seconds=2');
            return 222;
        }, 'bar');
        // 协程运行结束后,返回结果
        $result = $parallel->wait();
        return $result;
    }
}

4. parall助手函数【测试未通过

// 使用 parallel全局函数的形式调用
    public function test2()
    {
        $result = parallel([
            'foo' => function () {
                $client = $this->client->create();
                $client->get('127.0.0.1:9501/co_test/sleep?seconds=2');
                return 111;
            },
            'bar' => function () {
                $client = $this->client->create();
                $client->get('127.0.0.1:9501/co_test/sleep?seconds=2');
                return 222;
            }
        ]);
        return $result;
    }
上一篇:css 切角实现(全)


下一篇:基于SSM+微信小程序教师管理系统(教务1)