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: helloFiber 是异步 PHP 框架的基础。虽然你在大多数应用中不会直接使用它们,但了解它们有助于你使用异步库处理并发操作,例如 HTTP 请求或数据库查询,而不会造成阻塞。
挑战
简单让我们构建一个任务调度器,演示纤程如何暂停和恢复执行,并在纤程与主程序之间传递数据。你将创建一个系统,让任务可以被中断,以便在任务之间处理其他工作。
你将把代码分成两个文件:
TaskRunner.php:创建一个封装纤程功能、用于运行任务的TaskRunner类。这个类应该:- 包含一个私有属性,用于存储
Fiber实例 - 使用构造函数属性提升,在构造函数中接收任务名称(字符串)
- 包含一个
createTask(callable $task)方法,用给定的可调用对象创建一个新的 Fiber 并存储它 - 包含一个
start()方法,用于启动纤程,并返回纤程暂停时传出的值(或最终返回值) - 包含一个
continue(mixed $value)方法,用给定的值恢复纤程,并返回下一个暂停时传出的值(或最终返回值) - 包含一个
isFinished(): bool方法,用于返回纤程是否已终止
- 包含一个私有属性,用于存储
main.php:引入 TaskRunner 文件。你会收到两个输入:任务名称,以及要发送给纤程的消息。使用给定的任务名称创建一个
TaskRunner,然后使用createTask()定义一个任务,该任务会:- 首先暂停,并传出字符串
"Waiting for input" - 恢复时接收一个值
- 返回
"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: 打印最终结果
?>这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: PHP 在线编译器