ホームページ >バックエンド開発 >PHPチュートリアル >PHPのマルチスレッド処理の問題について
以下は、PHP マルチスレッドの問題、PHP の pthreads 拡張機能、curl_multi_init 関数に関するものです。そのような問題に遭遇して解決できない場合は、他の人がどのように解決したかを見てください。
Windows での php リアルマルチスレッド拡張機能 pthreads のインストールに関するチュートリアル
拡張機能のアドレス: http://docs.php.net/manual/zh/book.pthreads.php
Notes
php5.3 以降、そして、それはスレッドセーフなバージョンです。 Apache と php で使用されるコンパイラは一貫している必要があります。
phpinfo() を通じてスレッド セーフが有効になっている場合、それはスレッド セーフ バージョンを意味します。
phpinfo()でCompiler項目を表示することで、使用されているコンパイラを知ることができます。私のものはMSVC9 (Visual C++ 2008)です。
使用環境
32bit windows xp sp3、wampserver2.2d(php5.3.10-vc9 + apache2.2.21-vc9)。
1. pthreads 拡張機能をダウンロードします
ダウンロード アドレス: http://windows.php.net/downloads/pecl/releases/pthreads
私の環境では、pthreads-2.0.8-5.3-ts-vc9-x86 をダウンロードしました。
2.0.8 は pthreads のバージョンを表します。
5.3はphpのバージョンを表します。
ts は、php にはスレッドセーフなバージョンが必要であることを意味します。
vc9 は、php を Visual C++ 2008 コンパイラでコンパイルする必要があることを意味します。
x86 は 32 ビットを意味します
2. pthreads 拡張機能をインストールします
php_pthreads.dll をディレクトリ binphpext にコピーします。 (私のパスは D:wampbinphpphp5.3.10ext です)
pthreadVC2.dll をディレクトリ binphp にコピーします。 (私のパスは D:wampbinphpphp5.3.10 です)
pthreadVC2.dll をディレクトリ C:windowssystem32 にコピーします。
PHP設定ファイルphp.iniを開きます。最後に extension=php_pthreads.dll を追加します
ヒント! Windows システムでは、pthreadVC2.dll のパスを PATH 環境変数に追加する必要があります。 [マイ コンピュータ] --->マウスの右ボタン ---> [プロパティ] ---> [詳細設定] ---> 環境変数 --->システム変数 --->Path という名前のパスを検索 ---> ;編集--->変数値の末尾に pthreadVC2.dll のフル パスを追加します (私の場合は C:WINDOWSsystem32pthreadVC2.dll です)。
3. pthreads 拡張機能をテストします
class AsyncOperation extends \Thread { public function __construct($arg){ $this->arg = $arg; } public function run(){ if($this->arg){ printf("Hello %s\n", $this->arg); } } } $thread = new AsyncOperation("World"); if($thread->start()) $thread->join(); ?>
上記のコードを実行すると、Hello World が表示され、pthreads 拡張機能が正常にインストールされたことが示されます。
Thinkphp3.2.2の簡単な例を添付します
<?php namespace Home\Controller; class test extends \Thread { public $url; public $result; public function __construct($url) { $this->url = $url; } public function run() { if ($this->url) { $this->result = model_http_curl_get($this->url); } } } function model_http_curl_get($url) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_TIMEOUT, 5); curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)'); $result = curl_exec($curl); curl_close($curl); return $result; } for ($i = 0; $i < 10; $i++) { $urls[] = 'http://www.baidu.com/s?wd='. rand(10000, 20000); } /* 多线程速度测试 */ $t = microtime(true); foreach ($urls as $key=>$url) { $workers[$key] = new test($url); $workers[$key]->start(); } foreach ($workers as $key=>$worker) { while($workers[$key]->isRunning()) { usleep(100); } if ($workers[$key]->join()) { dump($workers[$key]->result); } } $e = microtime(true); echo "多线程耗时:".($e-$t)."秒<br>"; /* 单线程速度测试 */ $t = microtime(true); foreach ($urls as $key=>$url) { dump(model_http_curl_get($url)); } $e = microtime(true); echo "For循环耗时:".($e-$t)."秒<br>";
テスト結果は次のとおりです:
マルチスレッド時間: 2.8371710777282714844秒
ループ時間の場合: 10.941586017608642578秒
curl_multi _init()
<?php echo date("Y-m-d H:m:s",time()); echo " ";echo floor(microtime()*1000); echo "<br>";$mtime = explode(" ", microtime());$mtime = $mtime[1].($mtime[0] * 1000); $mtime2 = explode(".", $mtime); $mtime = $mtime2[0]; echo $mtime;echo "<br>"; $urls=array('http://www.a.com', 'http://www.b.com', 'http://www.c.com', 'http://www.d.com','http://www.e.com'); print_r(async_get_url($urls)); //[0]=>example1,[1]=>example2 echo "<br>"; echo date("Y-m-d H:m:s",time()); echo " "; echo floor(microtime()*1000); echo "<br>"; $mtime_ = explode(" ", microtime()); $mtime_ = $mtime_[1].($mtime_[0] * 1000); $mtime2_ = explode(".", $mtime_);$mtime_ = $mtime2_[0]; echo $mtime_; echo "<br>"; echo $mtime_ - $mtime; function async_get_url($url_array, $wait_usec = 0) { if (!is_array($url_array)) return false; $wait_usec = intval($wait_usec); $data = array(); $handle = array(); $running = 0; $mh = curl_multi_init(); // multi curl handler$i = 0; foreach($url_array as $url) { $ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // return don't printcurl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)'); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 302 redirectcurl_setopt($ch, CURLOPT_MAXREDIRS, 7); curl_multi_add_handle($mh, $ch); // 把 curl resource 放进 multi curl handler 里 $handle[$i++] = $ch;} /* 执行 */ do { curl_multi_exec($mh, $running); if ($wait_usec > 0) /* 每个 connect 要间隔多久 */ usleep($wait_usec); // 250000 = 0.25 sec} while ($running > 0);/* 读取资料 */ foreach($handle as $i => $ch) {$content = curl_multi_getcontent($ch); $data[$i] = (curl_errno($ch) == 0) ? $content : false;} /* 移除 handle*/ foreach($handle as $ch) { curl_multi_remove_handle($mh, $ch); } curl_multi_close($mh); return $data;} ?>
curl_multi_init() について
一般的に、curl_multi_init() の使用を考えるとき、目的は複数の URL を 1 つずつリクエストするのではなく、同時にリクエストすることです。そうでない場合は、curl_init() が必要になります。
ただし、curl_multi を使用すると、過剰な CPU 消費や Web ページのアニメーション一時停止などの現象が発生する可能性があります。curl_multi によって引き起こされるアニメーション一時停止の問題を解決する方法を参照してください。curl_multi を使用する手順をまとめます。次のように:
ステップ 1:curl_multi_init を呼び出す
ステップ 2:ループ内でcurl_multi_add_handleを呼び出すこのステップで注意する必要があるのは、curl_multi_add_handle の 2 番目のパラメーターが、curl_init のサブハンドルであるということです。
ステップ 3:curl_multi_exec を呼び出し続けます
ステップ 4:curl_multi_getcontent をループ内で呼び出し、必要に応じて結果を取得します
ステップ 5:curl_multi_remove_handle を呼び出し、単語ハンドルごとにcurl_closeを呼び出します
ステップ 6:curl_multi_close を呼び出します
関数の説明各関数:
curl_multi_init()
curl バッチ ハンドル リソースを初期化します。
curl_multi_add_handle()
curl_multi_exec()
curl_multi_remove_handle()
curl_multi_close()
curl_multi_getcontent()
curl_multi_info_read()
この記事は PHP マルチスレッドの問題について共有されています。ご質問があれば、コメントや提案を残していただければ幸いです。今後、編集者がこのような記事をたくさん紹介していきますので、ぜひご注目ください。
以上がPHPのマルチスレッド処理の問題についての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。