子進(jìn)程的創(chuàng)建
一般的子進(jìn)程的寫法是:
<?php$pid = pcntl_fork();if($pid == -1){ //創(chuàng)建失敗 die('could not fork');}else{ if($pid){ //從這里開始寫的代碼是父進(jìn)程的 exit("parent!"); } else{ //子進(jìn)程代碼,為防止不停的啟用子進(jìn)程造成系統(tǒng)資源被耗盡的情況,一般子進(jìn)程代碼運(yùn)行完成后,加入exit來確保子進(jìn)程正常退出。 exit("child"); }}?>上邊的代碼如果創(chuàng)建子進(jìn)程成功的話,系統(tǒng)就有了2個進(jìn)程,一個為父進(jìn)程,一個為子進(jìn)程,子進(jìn)程的id號為$pid。在系統(tǒng)運(yùn)行到$pid = pcntl_fork();時,在這個地方進(jìn)行分支,父子進(jìn)程各自開始運(yùn)行各自的程序代碼。代碼的運(yùn)行結(jié)果是parent 和child,很奇怪吧,為什么一個if和else互斥的代碼中,都輸出了結(jié)果?其實(shí)是像上邊所說的,代碼在pcntl_fork時,一個父進(jìn)程運(yùn)行parent,一個子進(jìn)程運(yùn)行了child。在代碼結(jié)果上就顯示了parent和child。至于誰先誰后的問題,這得要看系統(tǒng)資源的分配了。
如果需要起多個進(jìn)程來處理數(shù)據(jù),可以根據(jù)數(shù)據(jù)的數(shù)量,按照約定好的數(shù)量比如說1000條一個進(jìn)程來起子進(jìn)程。使用for循環(huán)就可以了。
#如果獲得的總數(shù)小于或等于0,等待60秒,并退出 if ($count <= 0) { sleep(60); exit; } #如果大于1000,計算需要起的進(jìn)程數(shù) if ($count > 1000) { $cycleSize = ceil($count/1000); } else { $cycleSize = 1; } for ($i=0; $i<$cycleSize; $i++) { $pid = pcntl_fork(); if($pid == -1) { break; } else { if($pid) { #父進(jìn)程獲得子進(jìn)程的pid,存入數(shù)組 $pidArr[] = $pid; } else { //開始發(fā)送,子進(jìn)程執(zhí)行完自己的任務(wù)后,退出。 exit; } } } while(count($pidArr) > 0) { $myId = pcntl_waitpid(-1, $status, WNOHANG); foreach($pidArr as $key => $pid) { if($myId == $pid) unset($pidArr[$key]); } }然后使用crontab,來使此PHP程序每隔一段時間自動執(zhí)行。
當(dāng)然,示例代碼比較簡單,具體還需要考慮怎么防止多個子進(jìn)程執(zhí)行到同一條數(shù)據(jù)或者當(dāng)前進(jìn)程處理數(shù)據(jù)未完成時,crontab又開始執(zhí)行PHP文件啟用新的進(jìn)程等等。
PHP多進(jìn)程實(shí)現(xiàn)方式
下面來系統(tǒng)地整理一下PHP多進(jìn)程的實(shí)現(xiàn)方式:
1. 直接方式
pcntl_fork() 創(chuàng)建一個進(jìn)程,在父進(jìn)程返回值是子進(jìn)程的pid,在子進(jìn)程返回值是0,-1表示創(chuàng)建進(jìn)程失敗。跟C非常相似。
測試腳本 test.php
<?php // example of multiple processes date_default_timezone_set( 'Asia/Chongqing'); echo "parent start, pid ", getmypid(), "/n" ; beep(); for ($i=0; $i<3; ++$i){ $pid = pcntl_fork(); if ($pid == -1){ die ("cannot fork" ); } else if ($pid > 0){ echo "parent continue /n"; for ($k=0; $k<2; ++$k){ beep(); } } else if ($pid == 0){ echo "child start, pid ", getmypid(), "/n" ; for ($j=0; $j<5; ++$j){ beep(); } exit ; } } // *** function beep(){ echo getmypid(), "/t" , date( 'Y-m-d H:i:s', time()), "/n" ; sleep(1); }?>
新聞熱點(diǎn)
疑難解答