在PHP中并行执行函数

时间:2010-06-08 14:37:26

标签: php parallel-processing

PHP可以调用函数而不等待它返回吗?所以像这样:

function callback($pause, $arg) {
    sleep($pause);
    echo $arg, "\n";
}

header('Content-Type: text/plain');
fast_call_user_func_array('callback', array(3, 'three'));
fast_call_user_func_array('callback', array(2, 'two'));
fast_call_user_func_array('callback', array(1, 'one'));

会输出

one (after 1 second)
two (after 2 seconds)
three (after 3 seconds)

而不是

three (after 3 seconds)
two (after 3 + 2 = 5 seconds)
one (after 3 + 2 + 1 = 6 seconds)

主脚本旨在作为永久进程(TCP服务器)运行。 callback()函数将从客户端接收数据,执行外部PHP脚本,然后根据传递给callback()的其他参数执行某些操作。问题是主脚本不能等待外部PHP脚本完成。外部脚本的结果很重要,因此exec('php -f file.php &')不是一个选项。


编辑: 许多人建议看看PCNTL,因此似乎可以实现这样的功能。 PCNTL在Windows中不可用,我现在无法访问Linux机器,所以我无法测试它,但如果有这么多人建议它,那么应该可以做到这一点:)

谢谢大家!

7 个答案:

答案 0 :(得分:12)

在Unix平台上,您可以启用PCNTL功能,并使用pcntl_fork分叉进程并在子进程中运行您的作业。

类似的东西:

function fast_call_user_func_array($func, $args) {
  if (pcntl_fork() == 0) {
    call_user_func_array($func, $args);
  }
}

调用pcntl_fork后,两个进程将从同一位置执行您的代码。父进程将获得从pcntl_fork返回的PID,而子进程将获得0。 (如果出现错误,父进程将返回-1,这值得在生产代码中检查。)

答案 1 :(得分:2)

您可以查看PHP Process Control:

http://us.php.net/manual/en/intro.pcntl.php

注意:这是不是线程,而是处理单独的进程。附加的开销更多。

答案 2 :(得分:2)

它不会解决你的问题到fork,保持父进程免费用于其他连接&行动?见http://www.php.net/pcntl_fork。如果您需要回复答案,您可能会听父母的套接字,并与孩子一起写。带有读取的简单while(true)循环可能会这样做,如果运行永久TCP服务器,可能已经具有该基本功能。另一个选择是跟踪你的childprocess-id,在一个地方保存一个可访问的商店(文件/数据库/ memcached等),在主进程中用一个带有WNOHANG的pcnt_wait来检查退出的进程,并从中检索数据。存储。

答案 3 :(得分:1)

如果使用pcntl_fork方法,可以在PHP中进行一些线程化。

http://ca.php.net/manual/en/function.pcntl-fork.php

我自己从未使用过这个,但它是如何在php.net上使用它的一些很好的例子。

答案 4 :(得分:0)

据我所知,PHP没有此功能

您可以使用不同的技术模拟该功能,如下所示: Parallel functions in PHP

答案 5 :(得分:0)

PHP不支持多线程,因此除了利用操作系统或Web服务器多处理功能之外别无选择。请注意,实际上您可以同时获取exec的结果和输出:

  

string exec(string $ command [,   array& $ output [,int& $ return_var   ]])

答案 6 :(得分:0)

至少可以通过使用pcntl_signal(SIGCHLD, SIG_IGN)忽略子信号来阻止父进程挂起,直到子进程完成。

所以,假设您想要分叉一个进程并执行另一个PHP函数,该函数需要一段时间而不会让父进程等待它完成(因为您希望主进程及时完成):

pcntl_signal(SIGCHLD, SIG_IGN);
$pid = pcntl_fork();
if ($pid < 0) {
  exit(0);
} elseif (!$pid) {
  my_slow_function();
  exit(0);
}
// Parent keeps executing and finishes before the child does

如果你想执行一个缓慢的外部脚本作为子进程,pcntl_exec很方便:

$script = array('/path/to/my/script'); // E.g. /home/my_user/my_script.php
pcntl_exec('/path/to/program/executable',$script); // E.g. /usr/bin/php