php实现并发
PHP 实现并发的方法
PHP 本身是单线程语言,但可以通过多种方式实现并发处理任务,提高程序执行效率。
多进程方式(PCNTL 扩展)
使用 PHP 的 PCNTL 扩展可以创建多个子进程来实现并发。该方法适用于 CLI 模式下的 PHP 脚本。
$pid = pcntl_fork();
if ($pid == -1) {
die('Could not fork');
} else if ($pid) {
// 父进程
pcntl_wait($status); // 等待子进程结束
} else {
// 子进程
// 执行任务代码
exit();
}
多线程方式(pthreads 扩展)
PHP 的 pthreads 扩展提供了多线程支持,但需要注意该扩展仅在线程安全的 PHP 版本中可用。
class MyThread extends Thread {
public function run() {
// 线程执行的代码
}
}
$thread = new MyThread();
$thread->start();
$thread->join();
异步非阻塞 I/O(Swoole 扩展)
Swoole 是一个高性能的 PHP 协程框架,提供了真正的异步非阻塞 I/O 支持。
$serv = new Swoole\Http\Server("0.0.0.0", 9501);
$serv->on('Request', function($request, $response) {
// 异步处理多个任务
$tasks = [
'task1' => function() { return doTask1(); },
'task2' => function() { return doTask2(); }
];
$results = [];
foreach ($tasks as $name => $task) {
go(function() use ($name, $task, &$results) {
$results[$name] = $task();
});
}
$response->end(json_encode($results));
});
$serv->start();
消息队列(Gearman/RabbitMQ)
使用消息队列可以将任务分发到多个工作进程异步处理。
// Gearman 客户端示例
$client = new GearmanClient();
$client->addServer();
$client->doBackground('job_name', 'workload');
// Worker 端
$worker = new GearmanWorker();
$worker->addServer();
$worker->addFunction('job_name', function($job) {
// 处理任务
return do_work($job->workload());
});
while ($worker->work());
协程(Coroutine)
PHP 8.1+ 内置了纤程(Fiber)支持,可以实现协程。
$fiber = new Fiber(function() {
// 协程代码
Fiber::suspend();
// 恢复后继续执行
});
$fiber->start();
$fiber->resume();
cURL 多请求
对于 HTTP 请求并发,可以使用 cURL 的多请求功能。
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch);
$handles[] = $ch;
}
$running = null;
do {
curl_multi_exec($mh, $running);
} while ($running > 0);
foreach ($handles as $ch) {
$response = curl_multi_getcontent($ch);
// 处理响应
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
并行 HTTP 请求(Guzzle)
使用 Guzzle 的异步客户端可以方便地实现并行 HTTP 请求。
$client = new GuzzleHttp\Client();
$promises = [
'request1' => $client->getAsync('http://example.com/1'),
'request2' => $client->getAsync('http://example.com/2')
];
$results = GuzzleHttp\Promise\Utils::unwrap($promises);
选择哪种并发实现方式取决于具体应用场景、性能需求和服务器环境。对于 Web 应用,通常推荐使用消息队列或 Swoole 等异步框架;对于 CLI 脚本,可以考虑多进程或多线程方式。






