PHP多進程處理並行處理任務實例

本文目的php

本文經過例子講解linux環境下,使用php進行併發任務處理,以及如何經過pipe用於進程間的數據同步。寫得比較簡單,做爲備忘錄。linux

PHP多進程web

經過pcntl_XXX系列函數使用多進程功能。注意:pcntl_XXX只能運行在php CLI(命令行)環境下,在web服務器環境下,會出現沒法預期的結果,請慎用!服務器

管道PIPE併發

管道用於承載簡稱之間的通信數據。爲了方便理解,能夠將管道比做文件,進程A將數據寫到管道P中,而後進程B從管道P中讀取數據。php提供的管道操做API與操做文件的API基本同樣,除了建立管道使用posix_mkfifo函數,讀寫等操做均與文件操做函數相同。固然,你能夠直接使用文件模擬管道,可是那樣沒法使用管道的特性了。函數

殭屍進程性能

子進程結束時,父進程沒有等待它(經過調用wait或者waitpid),那麼子進程結束後不會釋放全部資源(浪費呀!),這種進程被稱爲殭屍進程,他裏面存放了子進程結束時的相關數據,若是殭屍進程過多,會佔用大量系統資源(如內存),影響機器性能。this

代碼spa

廢話少說直接上代碼.net

/**
  * this is a demo for php fork and pipe usage. fork use
  * to create child process and pipe is used to sychoroize
  * the child process and its main process.
  * @author bourneli
  * @date: 2012-7-6
  */
 
define( "PC" , 10); // 進程個數
define( "TO" , 4); // 超時
define( "TS" , 4); // 事件跨度,用於模擬任務延時
 
if  (!function_exists( 'pcntl_fork' )) {
     die ( "pcntl_fork not existing" );
}
 
// 建立管道
$sPipePath  = "my_pipe." .posix_getpid();
if  (!posix_mkfifo( $sPipePath , 0666)) {
     die ( "create pipe {$sPipePath} error" );
}
 
// 模擬任務併發
for  ( $i  = 0; $i  < PC; ++ $i  ) {
     $nPID  = pcntl_fork(); // 建立子進程
     if  ( $nPID  == 0) {
         // 子進程過程
         sleep(rand(1,TS)); // 模擬延時
         $oW  = fopen ( $sPipePath , 'w' );
         fwrite( $oW , $i . "\n" ); // 當前任務處理完比,在管道中寫入數據
         fclose( $oW );
         exit (0); // 執行完後退出
     }
}
 
// 父進程
$oR  = fopen ( $sPipePath , 'r' );
stream_set_blocking( $oR , FALSE); // 將管道設置爲非堵塞,用於適應超時機制
$sData  = '' ; // 存放管道中的數據
$nLine  = 0;
$nStart  = time();
while  ( $nLine  < PC && (time() - $nStart ) < TO) {
     $sLine  = fread ( $oR , 1024);
     if  ( empty ( $sLine )) {
         continue ;  
     }  
     
     echo  "current line: {$sLine}\n" ;
     // 用於分析多少任務處理完畢,經過‘\n’標識
     foreach ( str_split ( $sLine ) as  $c ) {
         if  ( "\n"  == $c ) {
             ++ $nLine ;
         }
     }
     $sData  .= $sLine ;
}
echo  "Final line count:$nLine\n" ;
fclose( $oR );
unlink( $sPipePath ); // 刪除管道,已經沒有做用了
 
// 等待子進程執行完畢,避免殭屍進程
$n  = 0;
while  ( $n  < PC) {
     $nStatus  = -1;
     $nPID  = pcntl_wait( $nStatus , WNOHANG);
     if  ( $nPID  > 0) {
         echo  "{$nPID} exit\n" ;
         ++ $n ;
     }
}
 
// 驗證結果,主要查看結果中是否每一個任務都完成了
$arr2  = array ();
foreach ( explode ( "\n" , $sData ) as  $i ) { // trim all
     if  ( is_numeric (trim( $i ))) {
         array_push ( $arr2 , $i ); 
     }
}
$arr2  = array_unique ( $arr2 );
if  ( count ( $arr2 ) == PC) { 
     echo  'ok' ;
} else  {
     echo   "error count "  . count ( $arr2 ) . "\n" ;
     var_dump( $arr2 );
}


ok,完畢,註釋寫的比較清除,執行結果以下:

clip_image002

相關文章
相關標籤/搜索