Существует ли реалистичный способ реализации многопоточной модели в 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 = [ правильный идентификатор]
$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"];
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); }
if ($_REQUEST["sessionid"]) session_id($_REQUEST["sessionid"]); session_start(); var_dump($_SESSION);
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
Я знаю, что это старый вопрос, но для людей, ищущих, есть расширение 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/
Он поддерживает двунаправленную межпоточную связь, а также имеет встроенную защиту для уничтожения дочерних потоков (предотвращение сирот).
У вас может быть опция:
Как насчет 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