Как можно использовать многопоточность в PHP-приложениях

Существует ли реалистичный способ реализации многопоточной модели в PHP, действительно ли это или просто имитировать ее. Некоторое время назад было высказано предположение, что вы можете заставить операционную систему загружать другой экземпляр исполняемого файла PHP и обрабатывать другие одновременные процессы.

Проблема заключается в том, что когда PHP-код завершает выполнение экземпляра PHP, он остается в памяти, потому что нет способа его убить из PHP. Поэтому, если вы имитируете несколько потоков, вы можете себе представить, что произойдет. Поэтому я все еще ищу способ многопоточности, который можно эффективно или эффективно имитировать из PHP. Есть идеи?

Многопоточность возможна в php

Да, вы можете делать многопоточность в PHP с помощью pthreads

Из документации PHP :

pthreads – это объектно-ориентированный API, который предоставляет все инструменты, необходимые для многопоточности в PHP. Приложения PHP могут создавать, читать, писать, исполнять и синхронизировать с Threads, Workers и Threaded.

Предупреждение . Расширение pthreads нельзя использовать в среде веб-сервера. Поэтому потоки в PHP должны оставаться в приложениях на базе CLI.

Простой тест

#!/usr/bin/php <?php class AsyncOperation extends Thread { public function __construct($arg) { $this->arg = $arg; } public function run() { if ($this->arg) { $sleep = mt_rand(1, 10); printf('%s: %s -start -sleeps %d' . "\n", date("g:i:sa"), $this->arg, $sleep); sleep($sleep); printf('%s: %s -finish' . "\n", date("g:i:sa"), $this->arg); } } } // Create a array $stack = array(); //Initiate Multiple Thread foreach ( range("A", "D") as $i ) { $stack[] = new AsyncOperation($i); } // Start The Threads foreach ( $stack as $t ) { $t->start(); } ?> 

Первый забег

 12:00:06pm: A -start -sleeps 5 12:00:06pm: B -start -sleeps 3 12:00:06pm: C -start -sleeps 10 12:00:06pm: D -start -sleeps 2 12:00:08pm: D -finish 12:00:09pm: B -finish 12:00:11pm: A -finish 12:00:16pm: C -finish 

Второй прогон

 12:01:36pm: A -start -sleeps 6 12:01:36pm: B -start -sleeps 1 12:01:36pm: C -start -sleeps 2 12:01:36pm: D -start -sleeps 1 12:01:37pm: B -finish 12:01:37pm: D -finish 12:01:38pm: C -finish 12:01:42pm: A -finish 

Пример реального мира

 error_reporting(E_ALL); class AsyncWebRequest extends Thread { public $url; public $data; public function __construct($url) { $this->url = $url; } public function run() { if (($url = $this->url)) { /* * If a large amount of data is being requested, you might want to * fsockopen and read using usleep in between reads */ $this->data = file_get_contents($url); } else printf("Thread #%lu was not provided a URL\n", $this->getThreadId()); } } $t = microtime(true); $g = new AsyncWebRequest(sprintf("http://www.google.com/?q=%s", rand() * 10)); /* starting synchronization */ if ($g->start()) { printf("Request took %f seconds to start ", microtime(true) - $t); while ( $g->isRunning() ) { echo "."; usleep(100); } if ($g->join()) { printf(" and %f seconds to finish receiving %d bytes\n", microtime(true) - $t, strlen($g->data)); } else printf(" and %f seconds to finish, request failed\n", microtime(true) - $t); } 

почему вы не используете popen ?

 for ($i=0; $i<10; $i++) { // open ten processes for ($j=0; $j<10; $j++) { $pipe[$j] = popen('script2.php', 'w'); } // wait for them to finish for ($j=0; $j<10; ++$j) { pclose($pipe[$j]); } } 

Threading недоступен на складе PHP, но одновременное программирование возможно с использованием HTTP-запросов в виде асинхронных вызовов.

Если параметр таймаута завитка установлен равным 1 и использует тот же session_id для процессов, которые вы хотите связать друг с другом, вы можете связываться с переменными сеанса, как в моем примере ниже. С помощью этого метода вы даже можете закрыть свой браузер, и одновременный процесс все еще существует на сервере.

Не забудьте проверить правильный идентификатор сеанса, например:

http: //localhost/test/verifysession.php? sessionid = [ правильный идентификатор]

startprocess.php

 $request = "http://localhost/test/process1.php?sessionid=".$_REQUEST["PHPSESSID"]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $request); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 1); curl_exec($ch); curl_close($ch); echo $_REQUEST["PHPSESSID"]; 

process1.php

 set_time_limit(0); if ($_REQUEST["sessionid"]) session_id($_REQUEST["sessionid"]); function checkclose() { global $_SESSION; if ($_SESSION["closesession"]) { unset($_SESSION["closesession"]); die(); } } while(!$close) { session_start(); $_SESSION["test"] = rand(); checkclose(); session_write_close(); sleep(5); } с set_time_limit(0); if ($_REQUEST["sessionid"]) session_id($_REQUEST["sessionid"]); function checkclose() { global $_SESSION; if ($_SESSION["closesession"]) { unset($_SESSION["closesession"]); die(); } } while(!$close) { session_start(); $_SESSION["test"] = rand(); checkclose(); session_write_close(); sleep(5); } в set_time_limit(0); if ($_REQUEST["sessionid"]) session_id($_REQUEST["sessionid"]); function checkclose() { global $_SESSION; if ($_SESSION["closesession"]) { unset($_SESSION["closesession"]); die(); } } while(!$close) { session_start(); $_SESSION["test"] = rand(); checkclose(); session_write_close(); sleep(5); } 

verifysession.php

 if ($_REQUEST["sessionid"]) session_id($_REQUEST["sessionid"]); session_start(); var_dump($_SESSION); 

closeprocess.php

 if ($_REQUEST["sessionid"]) session_id($_REQUEST["sessionid"]); session_start(); $_SESSION["closesession"] = true; var_dump($_SESSION); 

В то время как вы не можете нить, у вас есть определенная степень управления процессом в php. Вот два полезных набора:

Функции управления процессом http://www.php.net/manual/en/ref.pcntl.php

Функции POSIX http://www.php.net/manual/en/ref.posix.php

Вы можете разветвить свой процесс с помощью pcntl_fork – вернуть PID дочернего элемента. Затем вы можете использовать posix_kill для использования этого PID.

Тем не менее, если вы убиваете родительский процесс, сигнал должен быть отправлен дочернему процессу, говоря ему, чтобы он умер. Если сам php не распознает это, вы можете зарегистрировать функцию для управления им и выполнить чистый выход, используя pcntl_signal.

использование потоков стало возможным благодаря расширению PECL pthreads

http://www.php.net/manual/en/book.pthreads.php

Я знаю, что это старый вопрос, но для людей, ищущих, есть расширение PECL, написанное на C, которое дает возможность многопоточности PHP теперь, оно расположено здесь https://github.com/krakjoe/pthreads

Вы можете имитировать потоки. PHP может запускать фоновые процессы через popen (или proc_open). Эти процессы могут быть переданы с помощью stdin и stdout. Конечно, эти процессы могут быть программой php. Это, вероятно, так близко, как вы доберетесь.

Вы можете использовать exec () для запуска сценария командной строки (например, командной строки php), и если вы подключите вывод к файлу, ваш скрипт не будет ждать завершения команды.

Я не могу вспомнить синтаксис CLI php, но вам нужно что-то вроде:

 exec("/path/to/php -f '/path/to/file.php' | '/path/to/output.txt'"); 

Я думаю, что для нескольких общих серверов хостинга по умолчанию отключен exec () по соображениям безопасности, но, возможно, стоит попробовать.

В зависимости от того, что вы пытаетесь сделать, вы также можете использовать curl_multi для его достижения.

Я знаю, что это устарело, но вы можете посмотреть http://phpthreadlib.sourceforge.net/

Он поддерживает двунаправленную межпоточную связь, а также имеет встроенную защиту для уничтожения дочерних потоков (предотвращение сирот).

У вас может быть опция:

  1. multi_curl
  2. Можно использовать системную команду для того же
  3. Идеальный сценарий – создание функции потоковой передачи на языке C и компиляция / настройка в PHP. Теперь эта функция будет функцией PHP.

Как насчет pcntl_fork?

проверьте нашу страницу руководства на примерах: PHP pcntl_fork

pcntl_fork не будет работать в среде веб-сервера, если включен безопасный режим . В этом случае он будет работать только в версии CLI для PHP.

Класс Thread доступен начиная с PECL pthreads ≥ 2.0.0.

Может быть, я что-то пропустил, но exec не работал как асинхронный для меня в среде Windows, которую я использовал в окнах, и это работало как шарм;)

 $script_exec = "c:/php/php.exe c:/path/my_ascyn_script.php"; pclose(popen("start /B ". $script_exec, "r")); 

Многопоточность означает одновременное выполнение нескольких задач или процессов, мы можем достичь этого в php, используя следующий код, хотя нет прямого способа достижения многопоточности в php, но мы можем добиться почти одинаковых результатов следующим образом.

 chdir(dirname(__FILE__)); //if you want to run this file as cron job for ($i = 0; $i < 2; $i += 1){ exec("php test_1.php $i > test.txt &"); //this will execute test_1.php and will leave this process executing in the background and will go //to next iteration of the loop immediately without waiting the completion of the script in the //test_1.php , $i is passed as argument . 

}

Test_1.php

 $conn=mysql_connect($host,$user,$pass); $db=mysql_select_db($db); $i = $argv[1]; //this is the argument passed from index.php file for($j = 0;$j<5000; $j ++) { mysql_query("insert into test set id='$i', comment='test', datetime=NOW() "); } 

Это будет выполнять test_1.php два раза одновременно, и оба процесса будут работать в фоновом режиме одновременно, так что вы сможете достичь многопоточности в php.

Этот парень сделал действительно хорошую работу. Многопоточность в php