当前位置: 首页 > 文档资料 > Swoole 中文文档 >

Coroutine\Channel

优质
小牛编辑
135浏览
2023-12-01

建议先查看概览,了解一些协程基本概念后再看此节。

通道,用于协程间通讯,支持多生产者协程和多消费者协程。底层自动实现了协程的切换和调度。

实现原理

  • 通道与PHPArray类似,仅占用内存,没有其他额外的资源申请,所有操作均为内存操作,无IO消耗
  • 底层使用PHP引用计数实现,无内存拷贝。即使是传递巨大字符串或数组也不会产生额外性能消耗
  • channel基于引用计数实现,是零拷贝的

使用示例

Co\run(function(){
    $chan = new Swoole\Coroutine\Channel(1);
    Swoole\Coroutine::create(function () use ($chan) {
        for($i = 0; $i < 100000; $i++) {
            co::sleep(1.0);
            $chan->push(['rand' => rand(1000, 9999), 'index' => $i]);
            echo "$i\n";
        }
    });
    Swoole\Coroutine::create(function () use ($chan) {
        while(1) {
            $data = $chan->pop();
            var_dump($data);
        }
    });
});

方法

__construct()

通道构造方法。

Swoole\Coroutine\Channel->__construct(int $capacity = 1)
  • 参数

    • int $capacity
      • 功能:设置容量 【必须为大于或等于1的整数】
      • 默认值1
      • 其它值:无

!> 底层使用PHP引用计数来保存变量,缓存区只需要占用 $capacity * sizeof(zval) 字节的内存,PHP7版本下zval16字节,如$capacity = 1024时,Channel最大将占用16K内存

!> 在Server中使用时必须在onWorkerStart之后创建

push()

向通道中写入数据。

Swoole\Coroutine\Channel->push(mixed $data, float $timeout = -1): bool;
  • 参数

    • mixed $data

      • 功能:push 数据 【可以是任意类型的PHP变量,包括匿名函数和资源】
      • 默认值:无
      • 其它值:无

      !> 为避免产生歧义,请勿向通道中写入空数据,如0false空字符串null

    • float $timeout

      • 功能:设置超时时间
      • 值单位: 秒【支持浮点型,如1.5表示1s+500ms
      • 默认值-1
      • 其它值:无
      • 版本影响:Swoole版本 >= v4.2.12

      !> 在通道已满的情况下,push会挂起当前协程,在约定的时间内,如果没有任何消费者消费数据,将发生超时,底层会恢复当前协程,push调用立即返回false,写入失败

  • 返回值

    • 执行成功返回true
    • 通道被关闭时,执行失败返回false,可使用$chan->errCode得到错误码
  • 扩展

    • 通道已满

      • 自动yield当前协程,其他消费者协程pop消费数据后,通道可写,将重新resume当前协程
      • 多个生产者协程同时push时,底层自动进行排队,底层会按照顺序逐个resume这些生产者协程
    • 通道为空

      • 自动唤醒其中一个消费者协程
      • 多个消费者协程同时pop时,底层自动进行排队,按照顺序逐个resume这些消费者协程

!> Coroutine\Channel使用本地内存,不同的进程之间内存是隔离的。只能在同一进程的不同协程内进行pushpop操作

pop()

从通道中读取数据。

Swoole\Coroutine\Channel->pop(float $timeout = -1): mixed;
  • 参数

    • float $timeout
      • 功能:设置超时时间
      • 值单位: 秒【支持浮点型,如1.5表示1s+500ms
      • 默认值:-1永不超时
      • 其它值:无
      • 版本影响:Swoole版本 >= v4.0.3
  • 返回值

    • 返回值可以是任意类型的PHP变量,包括匿名函数和资源
    • 通道被关闭时,执行失败返回false
  • 扩展

    • 通道已满

      • pop消费数据后,将自动唤醒其中一个生产者协程,让其写入新数据
      • 多个生产者协程同时push时,底层自动进行排队,按照顺序逐个resume这些生产者协程
    • 通道为空

      • 自动yield当前协程,其他生产者协程push生产数据后,通道可读,将重新resume当前协程
      • 多个消费者协程同时pop时,底层自动进行排队,底层会按照顺序逐个resume这些消费者协程

stats()

获取通道的状态。

Swoole\Coroutine\Channel->stats(): array;
  • 返回值

    返回一个数组,缓冲通道将包括4项信息,无缓冲通道返回2项信息

    • consumer_num 消费者数量,表示当前通道为空,有N个协程正在等待其他协程调用push方法生产数据
    • producer_num 生产者数量,表示当前通道已满,有N个协程正在等待其他协程调用pop方法消费数据
    • queue_num 通道中的元素数量
array(
  "consumer_num" => 0,
  "producer_num" => 1,
  "queue_num" => 10
);

close()

关闭通道。并唤醒所有等待读写的协程。

Swoole\Coroutine\Channel->close(): bool;

!> 唤醒所有生产者协程,push方法返回false;唤醒所有消费者协程,pop方法返回false

length()

获取通道中的元素数量。

Swoole\Coroutine\Channel->length(): int;

isEmpty()

判断当前通道是否为空。

Swoole\Coroutine\Channel->isEmpty(): bool;

isFull()

判断当前通道是否已满。

Swoole\Coroutine\Channel->isFull(): bool;

属性

capacity

通道缓冲区容量。

构造函数中设定的容量会保存在此,不过如果设定的容量小于1则此变量会等于1

Swoole\Coroutine\Channel->capacity: int;

errCode

获取错误码。

Swoole\Coroutine\Channel->errCode: int;
  • 返回值
对应常量作用
0SWOOLE_CHANNEL_OK默认 成功
-1SWOOLE_CHANNEL_TIMEOUT超时 pop失败时(超时)
-2SWOOLE_CHANNEL_CLOSEDchannel已关闭,继续操作channel