组件ThreadChannel::close()

ThreadChannel::close

(PHP 8.6+, True Async 1.0)

php
public ThreadChannel::close(): void

关闭通道。关闭后:

  • 调用 send() 将抛出 ThreadChannelException
  • 调用 recv() 继续返回缓冲区中已有的值,直到缓冲区排空。 一旦缓冲区为空,recv() 将抛出 ThreadChannelException
  • 当前在 send()recv() 中阻塞的任何线程都将被解除阻塞,并收到 ThreadChannelException

在已关闭的通道上调用 close() 是空操作 — 不会抛出异常。

close() 是向消费侧发出"流结束"信号的标准方式。生产者在发送完所有元素后关闭通道;消费者持续读取直到捕获到 ThreadChannelException

close() 本身是线程安全的,可以从任何线程调用。

示例

示例 #1 生产者发送完所有元素后关闭

php
<?php

use Async\ThreadChannel;
use function Async\spawn;
use function Async\spawn_thread;
use function Async\await;

spawn(function() {
    $channel = new ThreadChannel(10);

    $producer = spawn_thread(function() use ($channel) {
        foreach (['alpha', 'beta', 'gamma'] as $item) {
            $channel->send($item);
        }
        $channel->close(); // 发出信号:无更多数据
    });

    $consumer = spawn_thread(function() use ($channel) {
        try {
            while (true) {
                echo $channel->recv(), "\n";
            }
        } catch (\Async\ThreadChannelException) {
            echo "Stream ended\n";
        }
    });

    await($producer);
    await($consumer);
});

示例 #2 关闭解除等待接收方的阻塞

php
<?php

use Async\ThreadChannel;
use function Async\spawn;
use function Async\spawn_thread;
use function Async\await;

spawn(function() {
    $channel = new ThreadChannel(); // 无缓冲

    // 这个线程将在 recv() 中阻塞等待值
    $waiter = spawn_thread(function() use ($channel) {
        try {
            $channel->recv(); // 阻塞
        } catch (\Async\ThreadChannelException) {
            return "Unblocked by close()";
        }
    });

    // 从另一个线程关闭通道 — 解除等待者的阻塞
    spawn_thread(function() use ($channel) {
        $channel->close();
    });

    echo await($waiter), "\n";
});

示例 #3 两次调用 close() 是安全的

php
<?php

use Async\ThreadChannel;

$channel = new ThreadChannel(5);
$channel->close();
$channel->close(); // 空操作,不抛出异常

echo $channel->isClosed() ? "closed" : "open"; // "closed"

参见