在PHP CLI中使用并行线程运行大循环

Tom*_*Tom 6 php multithreading symfony

我在Symfony2/PHP中有一个计算昂贵的后端进程,我想运行多线程.

由于我迭代了数千个对象,我想我不应该为每个对象启动一个线程.我想有一个$ cores变量来定义我想并行的线程数,然后遍历循环并保持运行的那么多线程.因此,每次线程完成时,应启动具有下一个对象的新线程,直到完成所有对象.

查看pthreads文档并进行一些Google搜索,我找不到这种情况的可用示例.我发现的所有示例都有一次固定数量的线程,它们都没有遍历数千个对象.

有人能指出我正确的方向开始吗?我理解设置线程和加入它等的基础知识,但不了解如何在具有等待条件的循环中执行此操作.

Joe*_*ins 4

问题的答案是使用PoolWorker抽象。

基本思想是您::submit Threaded反对Pool,它会将其堆叠到下一个可用的Worker,将您的Threaded对象(循环)分布到所有Workers

以下是 PHP7(pthreads v3)的超级简单代码:

<?php
$jobs = [];
while (count($jobs) < 2000) {
    $jobs[] = mt_rand(0, 1999);
}

$pool = new Pool(8);

foreach ($jobs as $job) {
    $pool->submit(new class($job) extends Threaded {
        public function __construct(int $job) {
            $this->job = $job;
        }
        public function run() {
            var_dump($this->job);
        }
    });
}

$pool->shutdown();
?>
Run Code Online (Sandbox Code Playgroud)

显然,这些工作毫无意义。在现实世界中,我猜你的$jobs阵列不断增长,所以你可以只交换foreach一些do {} while,并继续寻找::submit新的工作。

在现实世界中,您将希望在同一循环中收集垃圾(只需调用Pool::collect不带参数的默认行为)。

值得注意的是,如果 PHP 确实不适合在多线程环境中工作,那么这一切都是不可能的……它确实是这样的。

问题的答案,但它并不能成为解决您问题的最佳方案

您在评论中提到您假设执行 Symfony 代码的 8 个线程将占用比 8 个进程更少的内存。事实并非如此,PHP 始终不共享任何内容。您可以预期 8 个 Symfony 线程占用的内存与 8 个 Symfony 进程一样多,事实上,还多一点。使用线程相对于进程的好处是它们可以相互通信、同步和(看起来)共享。

仅仅因为你可以,并不意味着你应该这样做。手头任务的最佳解决方案可能是使用一些现成的软件包或软件来完成所需的任务。

充分研究这些东西以实现强大的解决方案需要很长时间,而且您不会想部署第一个解决方案......

如果您决定忽略我的建议并尝试一下,您可以在 pthreads 的 github 存储库中找到许多示例。