Параллельное выполнение функций в PHP - PullRequest
10 голосов
/ 08 июня 2010

Может ли 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 &') не вариант.


Edit: Многие рекомендовали взглянуть на PCNTL, поэтому кажется, что такая функциональность может быть достигнута. PCNTL недоступен в Windows, и у меня сейчас нет доступа к машине с Linux, поэтому я не могу проверить ее, но если так много людей посоветовали это, то это должно сработать

Спасибо всем!

Ответы [ 7 ]

12 голосов
/ 08 июня 2010

На платформах Unix вы можете включить функции PCNTL и использовать pcntl_fork для разветвления процесса и запуска заданий в дочерних процессах.

Что-то вроде:

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

Как только вы вызовете pcntl_fork, два процесса выполнят ваш код с одной и той же позиции. Родительский процесс получит PID, возвращенный из pcntl_fork, а дочерний процесс получит 0. (В случае ошибки родительский процесс вернет -1, что стоит проверить в рабочем коде).

2 голосов
/ 08 июня 2010

Разве это не решит вашу проблему, если родительский процесс будет свободен для других соединений и действий?См. http://www.php.net/pcntl_fork. Если вам нужен ответ, вы можете прослушать сокет у родителя и написать с ребенком.Возможно использование простого цикла while (true) с чтением, и, возможно, у вас уже есть эта базовая функциональность, если вы используете постоянный TCP-сервер.Другой вариант - отслеживать ваши дочерние идентификаторы, хранить где-нибудь доступное хранилище (файл / база данных / memcached и т. Д.) С pcnt_wait в главном процессе с WNOHANG, чтобы проверить, какой процесс завершился, и извлечь данные измагазин.

2 голосов
/ 08 июня 2010

Вы можете проверить PHP Process Control:

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

Примечание: Это не многопоточность , но обработка отдельных процессовЕсть дополнительные накладные расходы.

1 голос
/ 08 июня 2010

Вы можете сделать несколько потоков в PHP, если используете метод pcntl_fork.

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

Я никогда не использовал это сам, но вот хороший пример того, как его использоватьна php.net.

0 голосов
/ 12 июня 2014

Вы можете, по крайней мере, предотвратить зависание родительского процесса до тех пор, пока дочерний процесс не будет выполнен, игнорируя дочерние сигналы с помощью 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
0 голосов
/ 08 июня 2010

PHP не поддерживает многопоточность, поэтому нет другого выбора, кроме как использовать возможности многопроцессорной обработки ОС или веб-сервера.Обратите внимание, что на самом деле вы можете получить как результат, так и результат exec :

string exec (строка $ command [, массив & $ output [, int & $ return_var]])

0 голосов
/ 08 июня 2010

Насколько мне известно, PHP не обладает этой функциональностью

Вы можете эмулировать функцию, используя другую технику, например: Параллельные функции в PHP

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...