PHP并发处理与协程入门
说到PHP并发,传统PHP-FPM每个请求一个进程。但Swoole扩展让PHP有了协程能力。今天说说PHP中协程和并发处理。
生成器是协程的基础。每个yield点都可以暂停和恢复。
```php
class Task
{
private Generator $coroutine;
private string $name;
private bool $finished = false;
public function __construct(string $name, Generator $coroutine)
{
$this->name = $name;
$this->coroutine = $coroutine;
}
public function run(): void
{
if ($this->finished) return;
if ($this->coroutine->valid()) {
$this->coroutine->send(null);
} else {
$this->finished = true;
}
}
public function isFinished(): bool
{
return $this->finished || !$this->coroutine->valid();
}
public function getName(): string { return $this->name; }
}
class Scheduler
{
private array $tasks = [];
public function add(Task $task): void
{
$this->tasks[] = $task;
}
public function run(): void
{
while (!empty($this->tasks)) {
$task = array_shift($this->tasks);
$task->run();
if (!$task->isFinished()) {
$this->tasks[] = $task;
}
}
}
}
function task1(): Generator
{
for ($i = 1; $i <= 3; $i++) {
echo "任务1: 第{$i}步\n";
yield;
}
}
function task2(): Generator
{
for ($i = 1; $i <= 2; $i++) {
echo "任务2: 第{$i}步\n";
yield;
}
}
$scheduler = new Scheduler();
$scheduler->add(new Task('A', task1()));
$scheduler->add(new Task('B', task2()));
$scheduler->run();
?>
Swoole协程的用法。
```php
// Swoole协程
use function Swoole\Coroutine\go;
use function Swoole\Coroutine\run;
run(function () {
go(function () {
Swoole\Coroutine::sleep(1);
echo "协程1完成\n";
});
go(function () {
Swoole\Coroutine::sleep(2);
echo "协程2完成\n";
});
echo "主协程\n";
});
?>
协程在IO密集场景下优势明显。
```php
function simulateIO(string $name, int $ms): Generator
{
echo "{$name}: 开始\n";
yield;
echo "{$name}: 完成\n";
}
$scheduler = new Scheduler();
$scheduler->add(new Task('请求API1', simulateIO('请求API1', 2000)));
$scheduler->add(new Task('请求API2', simulateIO('请求API2', 1000)));
$start = microtime(true);
$scheduler->run();
echo "总耗时: " . round((microtime(true) - $start) * 1000) . "ms\n";
?>
协程在IO操作时让出CPU,等IO完成后再恢复执行。这让单进程可以处理大量并发连接。生成器实现的协程虽然不能实现真正的并行,但在IO密集场景下可以提升性能。生产环境建议用Swoole扩展。
PHP并发处理与协程入门