代码之家  ›  专栏  ›  技术社区  ›  binaryLV

在PHP中并行执行函数

  •  10
  • binaryLV  · 技术社区  · 15 年前

    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脚本,然后根据传递给 回退() . 问题是主脚本不能等待外部PHP脚本完成。外部脚本的结果很重要,因此 exec('php -f file.php &') 不是选项。


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

    谢谢大家!

    7 回复  |  直到 10 年前
        1
  •  12
  •   Chris    15 年前

    在UNIX平台上,您可以启用PCNTL函数,并使用 pcntl_fork 以分叉进程并在子进程中运行作业。

    类似:

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

    一旦你打电话 叉形叉 ,两个进程将从同一位置执行代码。父进程将从返回PID 叉形叉 ,而子进程将 0 . (如果有错误,父进程将返回 -1 ,这在生产代码中是值得检查的)。

        2
  •  2
  •   webbiedave    15 年前

    您可以查看php进程控制:

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

    注:这是 不穿线 但是处理不同的过程。附加了更多的开销。

        3
  •  2
  •   Wrikken    15 年前

    它是否可以解决您的分叉问题,使父进程不受其他连接和操作的限制?见 http://www.php.net/pcntl_fork . 如果你需要一个答案,你可以听父母的插座,然后和孩子一起写。一个带有read的简单while(true)循环可能会这样做,如果您运行一个永久的TCP服务器,那么您可能已经拥有了这个基本功能。另一种选择是跟踪子进程ID,在某个地方保留一个可访问的存储(文件/数据库/memcached等),在主进程中使用wnohang等待PCNT检查哪个进程已退出,并从存储中检索数据。

        4
  •  1
  •   HoLyVieR    15 年前

    如果使用pcntl_fork方法,可以在php中执行一些线程。

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

    我自己从来没有用过这个,但是下面是一些如何在php.net上使用它的好例子。

        5
  •  0
  •   zaczap    15 年前

    据我所知,PHP没有这个功能

    您可以使用不同的技术来模拟函数,例如: Parallel functions in PHP

        6
  •  0
  •   nuqqsa    15 年前

    PHP不支持多线程,因此除了利用操作系统或Web服务器的多处理功能之外,没有其他选择。请注意,实际上您可以获取 exec :

    string exec(字符串$command[, 数组&$output[,int&$return_var ])

        7
  •  0
  •   aruanoc    10 年前

    至少可以通过忽略子进程的信号来防止父进程挂起,直到子进程完成为止,方法是使用 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