Linux下PHP程序使用多線程?
引言
別的語言都在一窩蜂地搞編譯,搞虛擬機,搞多線程,提高效率。我們整天敲 PHP 代碼,除了 Nginx 調用 php-fpm 拉取 PHP 文件的解析外,對于多線程有多少了解?
請問,PHP 能不能使用多線程?如果能,怎么實現的?
本文就帶你打開這個疑問。
學習時間這個問題的答案是肯定的,PHP 可以使用多線程。我們借助于 pthreads 實現:
該項目提供了與基于Posix Threads的PHP兼容的多線程。
有啥亮點沒?下面這些全是:
一個易于使用,快速學習的面向對象的PHP 7.2線程API執行所有預定義和用戶聲明的方法和函數,包括閉包。包括現成的同步無限的可能性...需要一些擴展的基礎的支持,PHP 7.2 及以上版本,ZTS Enabled ( Thread Safety ),Posix Threads Implementation。
還有一些注意事項:
pthreads是一個面向對象的API,它提供了PHP中多線程所需的所有工具。 PHP應用程序可以創建,讀取,寫入,執行并與線程,輔助對象和線程對象同步。 警告:pthreads擴展名不能在Web服務器環境中使用。 因此,PHP中的線程應僅保留給基于CLI的應用程序使用。
命令行應用腳本完全適用,這也與我們編寫 Bash,Python等等類似。下面舉一個例子:
然后執行一次:
再執行一次:
實際運用上面的代碼是個示例性質的應用,僅僅是為了展示多線程運行。下面來一段業務代碼。
該類模擬一個url請求。因為網絡問題,有可能失敗,或者不確定返回時間,所以適合并行。接著我們使用該類進行多網絡請求并發。為了減輕系統負荷,使用微秒延時。
$t = microtime(true);
$g = new AsyncWebRequest(sprintf("http://www.google.com/?q=%s", rand() * 10));
實例化之后,我們發起請求:
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);
}
其他方案如果不用 pthreads 庫提供的能力,該怎么寫并行的多任務呢?其實 PHP 提供了一個 popen 函數,用于打開進程文件指針。
popen 返回一個和 fopen 所返回的相同的文件指針,只不過它是單向的(只能用于讀或寫)并且必須用 pclose 來關閉。此指針可以用于 fgets,fgetss 和 fwrite。 當模式為 'r',返回的文件指針等于命令的 STDOUT,當模式為 'w',返回的文件指針等于命令的 STDIN。
直接上代碼:
for ($i=0; $i<10; $i++) { // 打開10個進程 for ($j=0; $j<10; $j++) { $pipe[$j] = popen('script2.php', 'w'); } // 等待完成 for ($j=0; $j<10; ++$j) { pclose($pipe[$j]); } }
大家看到了實現的方法與 pthreads 完全不同,這段代碼仍然是阻塞運行,只不過同時打開10個進程,并行運行。
并行與多線程完全不同。不過,可視作一個簡單的解決方案吧。
寫在最后經過上述兩種實現方法,大家應該對于多線程,多進程,并行這些概念有一些認識了。
Happy coding :_)
我是 @程序員小助手 ,持續分享編程知識,歡迎關注。