PHP多进程处理并行处理任务实例
2019獨角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
本文目的
本文通過例子講解linux環(huán)境下,使用php進行并發(fā)任務(wù)處理,以及如何通過pipe用于進程間的數(shù)據(jù)同步。寫得比較簡單,作為備忘錄。
PHP多進程
通過pcntl_XXX系列函數(shù)使用多進程功能。注意:pcntl_XXX只能運行在php CLI(命令行)環(huán)境下,在web服務(wù)器環(huán)境下,會出現(xiàn)無法預(yù)期的結(jié)果,請慎用!
管道PIPE
管道用于承載簡稱之間的通訊數(shù)據(jù)。為了方便理解,可以將管道比作文件,進程A將數(shù)據(jù)寫到管道P中,然后進程B從管道P中讀取數(shù)據(jù)。php提供的管道操作API與操作文件的API基本一樣,除了創(chuàng)建管道使用posix_mkfifo函數(shù),讀寫等操作均與文件操作函數(shù)相同。當(dāng)然,你可以直接使用文件模擬管道,但是那樣無法使用管道的特性了。
僵尸進程
子進程結(jié)束時,父進程沒有等待它(通過調(diào)用wait或者waitpid),那么子進程結(jié)束后不會釋放所有資源(浪費呀!),這種進程被稱為僵尸進程,他里面存放了子進程結(jié)束時的相關(guān)數(shù)據(jù),如果僵尸進程過多,會占用大量系統(tǒng)資源(如內(nèi)存),影響機器性能。
代碼
廢話少說直接上代碼
/** ? * 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); // 進程個數(shù) define( "TO" , 4); // 超時 define( "TS" , 4); // 事件跨度,用于模擬任務(wù)延時 if? (!function_exists( 'pcntl_fork' )) { ???? die ( "pcntl_fork not existing" ); } // 創(chuàng)建管道 $sPipePath? = "my_pipe." .posix_getpid(); if? (!posix_mkfifo( $sPipePath , 0666)) { ???? die ( "create pipe {$sPipePath} error" ); } // 模擬任務(wù)并發(fā) for? ( $i? = 0; $i? < PC; ++ $i? ) { ???? $nPID? = pcntl_fork(); // 創(chuàng)建子進程 ???? if? ( $nPID? == 0) { ???????? // 子進程過程 ???????? sleep(rand(1,TS)); // 模擬延時 ???????? $oW? = fopen ( $sPipePath , 'w' ); ???????? fwrite( $oW , $i . "\n" ); // 當(dāng)前任務(wù)處理完比,在管道中寫入數(shù)據(jù) ???????? fclose( $oW ); ???????? exit (0); // 執(zhí)行完后退出 ???? } } // 父進程 $oR? = fopen ( $sPipePath , 'r' ); stream_set_blocking( $oR , FALSE); // 將管道設(shè)置為非堵塞,用于適應(yīng)超時機制 $sData? = '' ; // 存放管道中的數(shù)據(jù) $nLine? = 0; $nStart? = time(); while? ( $nLine? < PC && (time() - $nStart ) < TO) { ???? $sLine? = fread ( $oR , 1024); ???? if? ( empty ( $sLine )) { ???????? continue ;?? ???? }?? ????? ???? echo? "current line: {$sLine}\n" ; ???? // 用于分析多少任務(wù)處理完畢,通過‘\n’標(biāo)識 ???? foreach ( str_split ( $sLine ) as? $c ) { ???????? if? ( "\n"? == $c ) { ???????????? ++ $nLine ; ???????? } ???? } ???? $sData? .= $sLine ; } echo? "Final line count:$nLine\n" ; fclose( $oR ); unlink( $sPipePath ); // 刪除管道,已經(jīng)沒有作用了 // 等待子進程執(zhí)行完畢,避免僵尸進程 $n? = 0; while? ( $n? < PC) { ???? $nStatus? = -1; ???? $nPID? = pcntl_wait( $nStatus , WNOHANG); ???? if? ( $nPID? > 0) { ???????? echo? "{$nPID} exit\n" ; ???????? ++ $n ; ???? } } // 驗證結(jié)果,主要查看結(jié)果中是否每個任務(wù)都完成了 $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,完畢,注釋寫的比較清除,執(zhí)行結(jié)果如下:
轉(zhuǎn)載于:https://my.oschina.net/u/247923/blog/282663
總結(jié)
以上是生活随笔為你收集整理的PHP多进程处理并行处理任务实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JTable demo
- 下一篇: php相应的扩展的对应链接地址