タグ: #PHP
PHPで最大N個のプロセスを並列に実行するクラスを作成しました。
マルチスレッドのデザインパターン Thread-Per-Message にあたるようです。ただPHPにはスレッドがないので、プロセスで代用しています。また最大起動プロセス数を超えた時点で、親プロセスが待ってしまいます。
ProcessPerMessageクラスの概要
ProcessPerMessage() コンストラクタ(同時実行プロセス数と子プロセスの最大実行時間を指定できる) invocation() 新たなプロセスを起動する(実行する関数と引数を指定する) shutdown() 全プロセスの終了を待つ 使用例
<?php declare(ticks=1); //ProcessPerMessageを利用するために必要 require_once("ProcessPerMessage.php"); //プロセスプール生成 $option = array('max_process' => 10,'child_max_runtime' => 120); $pool = new ProcessPerMessage($option); for($i = 0; $i < 500; $i++) { //プロセスの起動状況を表示 $pool->dump(); //プロセス起動 $option = array('func' => 'readRss','args' => $i); $pool->invocation($option); } //プロセスの終了を待つ $pool->shutdown(); //プロセスが実行する関数 function readRss($url) { $sleep = rand(2,10); sleep($sleep); }クラス本体
class ProcessPerMessage { //■ コンストラクタ function ProcessPerMessage($option) { //同時実行プロセス数 $this->max_process = 10; if (isset($option['max_process'])) { $this->max_process = intval($option['max_process']); } //子プロセスの最大実行時間 $this->child_max_runtime = 60; //1分 if (isset($option['child_max_runtime'])) { $this->child_max_runtime = intval($option ['child_max_runtime']); } //起動中のプロセスID一覧 $this->pids = array(); } //■ 新しいプロセス起動 function invocation($option) { $func = null; if (isset($option['func'])){ $func = $option['func']; } else { trigger_error("関数を指定してください"); } $args = null; if (isset($option['args'])){ $args = $option['args']; } $pid = pcntl_fork(); if ( $pid == -1 ) { trigger_error("プロセスの起動に失敗しました。"); } else if ( $pid ) { // 親プロセス $this->pids[ $pid ] = TRUE; //起動最大値を超えている場合は、子プロセスの終了を待つ if ( count( $this->pids ) >= $this->max_process ) { unset( $this->pids[ pcntl_waitpid( -1, $status, WUNTRACED ) ] ); } } else { //子プロセス // 120 秒後に強制終了 pcntl_alarm( $this->child_max_runtime ); call_user_func($func, $args); exit; } } //■ 全ての処理が終了するまで待機 function shutdown() { while ( count( $this->pids ) > 0 ) { unset( $this->pids[ pcntl_waitpid( -1, $status, WUNTRACED ) ] ); } } //■ デバッグ情報取得 function getDebugInfo() { $msg = "-------\n"; foreach($this->pids as $pid => $v) { $msg .= "$pid\n"; } $msg .= "-------\n"; return $msg; } //■ デバッグ情報表示 function dump() { $msg = $this->getDebugInfo(); echo($msg); } }
PHP 最大N個のプロセスを並列実行 - nishimura_snの日記
pnctlオプションを付けてコンパイルしたPHPから利用できます。
1年前 | 固定リンク | 2010年 8月 27日 | 
