Выполнение функций параллельно в PHP

Может ли 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-машине, поэтому я не могу его протестировать, но если так много людей посоветовали это, то он должен сделать трюк 🙂

Всем спасибо!

    На платформах Unix вы можете включить функции pcntl_fork и использовать 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 , что стоит проверить в производственном коде).

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

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

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

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

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

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

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

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

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

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

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

    По крайней мере, вы можете не допустить, чтобы родительский процесс зависал, пока дочерний процесс не будет выполнен, игнорируя дочерние сигналы, используя 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'); // Eg /home/my_user/my_script.php pcntl_exec('/path/to/program/executable',$script); // Eg /usr/bin/php