Menu
CoddyTech

Fiber(PHP 8.1)

本课属于 Coddy PHP 学习旅程的“面向对象编程”单元。第 60 课,共 91 课。

Fibers 是 PHP 8.1 的一项特性,可以实现可中断的代码执行。与从头到尾运行的普通函数不同,fiber 可以在执行过程中暂停,并在之后恢复,同时保留暂停期间的状态。

将可调用对象传递给 Fiber 类来创建一个纤程,然后使用 start() 启动它:

<?php
$fiber = new Fiber(function(): void {
    echo "Step 1\n";
    Fiber::suspend();
    echo "Step 2\n";
});

$fiber->start();
echo "Between steps\n";
$fiber->resume();

输出:

Step 1
Between steps
Step 2

纤程运行到遇到 Fiber::suspend() 时会暂停,然后控制权返回主代码。调用 resume() 会从暂停的位置继续执行。

Fiber 在暂停和恢复时也可以传递值:

<?php
$fiber = new Fiber(function(): string {
    $value = Fiber::suspend("paused");
    return "Received: $value";
});

$suspended = $fiber->start();
echo "$suspended\n";

$result = $fiber->resume("hello");
echo $result;

输出:

paused
Received: hello

Fiber 是异步 PHP 框架的基础。虽然你在大多数应用中不会直接使用它们,但了解它们有助于你使用异步库处理并发操作,例如 HTTP 请求或数据库查询,而不会造成阻塞。

challenge icon

挑战

简单

让我们构建一个任务调度器,演示纤程如何暂停和恢复执行,并在纤程与主程序之间传递数据。你将创建一个系统,让任务可以被中断,以便在任务之间处理其他工作。

你将把代码分成两个文件:

  • TaskRunner.php:创建一个封装纤程功能、用于运行任务的 TaskRunner 类。这个类应该:
    • 包含一个私有属性,用于存储 Fiber 实例
    • 使用构造函数属性提升,在构造函数中接收任务名称(字符串)
    • 包含一个 createTask(callable $task) 方法,用给定的可调用对象创建一个新的 Fiber 并存储它
    • 包含一个 start() 方法,用于启动纤程,并返回纤程暂停时传出的值(或最终返回值)
    • 包含一个 continue(mixed $value) 方法,用给定的值恢复纤程,并返回下一个暂停时传出的值(或最终返回值)
    • 包含一个 isFinished(): bool 方法,用于返回纤程是否已终止
  • main.php:引入 TaskRunner 文件。你会收到两个输入:任务名称,以及要发送给纤程的消息。

    使用给定的任务名称创建一个 TaskRunner,然后使用 createTask() 定义一个任务,该任务会:

    1. 首先暂停,并传出字符串 "Waiting for input"
    2. 恢复时接收一个值
    3. 返回 "Completed: [received value]"

    启动任务,并打印它第一次暂停时传出的内容。然后打印 "Processing...",以展示纤程暂停期间正在进行其他工作。最后,将消息输入传给纤程以恢复它,并打印最终结果。

这个挑战展示了纤程如何实现协作式多任务处理。任务会在合适的位置暂停,主程序处理其他工作,然后用新数据恢复任务。纤程会在整个过程中保持自身状态,并从暂停的位置准确继续执行。

亲手试试

<?php

require_once 'TaskRunner.php';

// 读取输入
$taskName = trim(fgets(STDIN));
$message = trim(fgets(STDIN));

// TODO: 用给定的任务名称创建一个 TaskRunner

// TODO: 使用 createTask() 定义一个任务,使其:
// 1. 首先用字符串 "Waiting for input" 暂停
// 2. 恢复时接收一个值
// 3. 返回 "Completed: [received value]"

// TODO: 启动任务,并打印它首次暂停时返回的内容

// TODO: 打印 "Processing...",表示 fiber 两次暂停之间仍有工作在进行

// TODO: 传入消息输入,继续运行 fiber

// TODO: 打印最终结果

?>
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: PHP 在线编译器