PHP本身不支援多線程,多進程支援的也不是特別好,網上找到一份多進程代碼(http://jasonyu.cn/html/2010/294.html),寫了一個測試程式簡單測了一下,可以運行,但是離上線還差得很遠。
<?php/** * Project: Signfork: php多線程庫 * File: Signfork.class.php */class Signfork{ /** * 設定子進程通訊檔案所在目錄 * @var string */ private $tmp_path='/tmp/'; /** * Signfork引擎主啟動方法 * 1、判斷$arg類型,類型為數組時將值傳遞給每個子進程;類型為數值型時,代表要建立的進程數. * @param object $obj 執行對象 * @param string|array $arg 用於對象中的__fork方法所執行的參數 * 如:$arg,自動分解為:$obj->__fork($arg[0])、$obj->__fork($arg[1])… * @return array 返回 array(子進程式列=>子進程執行結果); */ public function run($obj,$arg=1){ if(!method_exists($obj,'__fork')){ exit('Method "__fork" not found!'); } if(is_array($arg)){ $i=0; foreach($arg as $key=>$val){ $spawns[$i]=$key; $i++; $this->spawn($obj,$key,$val); } $spawns['total']=$i; }elseif($spawns=intval($arg)){ for($i = 0; $i < $spawns; $i++){ $this->spawn($obj,$i); } }else{ exit('Bad argument!'); } if($i>1000) exit('Too many spawns!'); return $this->request($spawns); } /** * Signfork主進程式控制制方法 * 1、$tmpfile 判斷子進程檔案是否存在,存在則子進程執行完畢,並讀取內容 * 2、$data收集子進程運行結果及資料,並用於最終返回 * 3、刪除子進程檔案 * 4、輪詢一次0.03秒,直到所有子進程執行完畢,清理子進程資源 * @param string|array $arg 用於對應每個子進程的ID * @return array 返回 array([子進程式列]=>[子進程執行結果]); */ private function request($spawns){ $data=array(); $i=is_array($spawns)?$spawns['total']:$spawns; for($ids = 0; $ids<$i; $ids++){ while(!($cid=pcntl_waitpid(-1, $status, WNOHANG)))usleep(30000); $tmpfile=$this->tmp_path.'sfpid_'.$cid; $data[$spawns['total']?$spawns[$ids]:$ids]=file_get_contents($tmpfile); unlink($tmpfile); } return $data; } /** * Signfork子進程執行方法 * 1、pcntl_fork 產生子進程 * 2、file_put_contents 將'$obj->__fork($val)'的執行結果存入特定序列命名的文本 * 3、posix_kill殺死當前進程 * @param object $obj 待執行的對象 * @param object $i 子進程的序列ID,以便於返回對應每個子進程資料 * @param object $param 用於輸入對象$obj方法'__fork'執行參數 */ private function spawn($obj,$i,$param=null){ if(pcntl_fork()===0){ $cid=getmypid(); file_put_contents($this->tmp_path.'sfpid_'.$cid,$obj->__fork($param)); posix_kill($cid, SIGTERM); exit; } }}?>
測試程式如下:
<?phprequire_once(dirname(__FILE__) . '/Signfork.class.php');class ExecObj{ public function __fork($param){ return getmypid(); } }echo getmypid()."\n";$signfork = new Signfork();$result = $signfork->run(new ExecObj(),5);foreach ($result as $key=>$val){ echo $key." ".$val."\n";}?>