phpでマルチスレッド


またまた自作フレームワーク用に組み込みたかった機能の話

特にfile_get_contentsなどの相手側の応答いかんで処理時間がかわるような場合
同時にだーって流しておきたいなーとはおもったんですが、
考えていたやりかたはモジュール版だと使えないということが発覚・・
(pcntl_forkって関数)

で今回みっけたのは curl_multi
PHP curl_multi example of parallel GET requests

注意点としては、各ハンドラが独自にキャッシュしてるから
ハンドルを変更せず再度 curl_multi_exec しても
トライせずにキャッシュを返すことかなぁ
(その場合一旦ハンドラを解除して再セットすればOKらしい)

なので、こんな感じでクラスを作って
localhostのphpファイルを呼び出せば
簡単にマルチスレッドでプログラムが動かせると。

まあよっぽどのことがないと使わないとおもいますが。

というかこれ、どこまでいけるんだろう。

Class Parallel {

    public $result;

    public function __construct() {
    }

    public function execute($urlList = array()) {
        if (count($urlList) > 0) {
            $channel = array();
            $uniqueUrls = array();
            $uniqueUrls = array_unique($urlList);

            //マルチプロセスハンドラ
            $multiHandle = curl_multi_init();

            //URLに一つづつチャンネルを割り当てる
            foreach ($uniqueUrls as $k=>$v) {
                $channel[$k] = curl_init($v);
                curl_setopt($channel[$k], CURLOPT_RETURNTRANSFER, 1);
                curl_multi_add_handle($multiHandle,$channel[$k]);
            }

            while (CURLM_CALL_MULTI_PERFORM == ($execReturn = curl_multi_exec($multiHandle,$isActive))) {
            }

            while ($isActive && $execReturn == CURLM_OK) {
                if (curl_multi_select($multiHandle) != -1) {
                    while (CURLM_CALL_MULTI_PERFORM == ($execReturn = curl_multi_exec($multiHandle,$isActive))) {
                    }
                }
            }

            if ($execReturn != CURLM_OK) {
                return false;
            }

            $resultData = array();
            foreach ($uniqueUrls as $k=>$v) {
                $curlError = curl_error($channel[$k]);
                if ($curlError == "") {
                    $resultData[$k] = curl_multi_getcontent($channel[$k]);
                } else {
                    $resultData[$k] = 'error';
                }
                curl_multi_remove_handle($multiHandle,$channel[$k]);
                curl_close($channel[$k]);
            }

            curl_multi_close($multiHandle);

            $this->result = $resultData;
            return true;
        } else {
            return false;
        }
    }

}

Leave a Reply