ホームページ  >  記事  >  バックエンド開発  >  PHPのマルチスレッド処理の問題について

PHPのマルチスレッド処理の問題について

PHPz
PHPzオリジナル
2017-11-10 10:36:562825ブラウズ

以下は、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, &#39;Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)&#39;);  
    $result = curl_exec($curl);  
    curl_close($curl);  
    return $result;  
}
for ($i = 0; $i < 10; $i++) {
    $urls[] = &#39;http://www.baidu.com/s?wd=&#39;. 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(&#39;http://www.a.com&#39;, &#39;http://www.b.com&#39;, &#39;http://www.c.com&#39;, &#39;http://www.d.com&#39;,&#39;http://www.e.com&#39;); 
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&#39;t printcurl_setopt($ch, CURLOPT_TIMEOUT, 30);
 curl_setopt($ch, CURLOPT_USERAGENT, &#39;Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)&#39;);
 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ハンドルリソースをcurlバッチセッションに追加します。 curl_multi_add_handle() 関数には 2 つのパラメータがあります。最初のパラメータは CURL バッチ ハンドル リソースを表し、2 番目のパラメータは別の CURL ハンドル リソースを表します。


curl_multi_exec()

curl バッチ ハンドルを解析します。curl_multi_exec() 関数には 2 つのパラメーターがあり、最初のパラメーターはバッチ ハンドル リソースを表し、2 番目のパラメーターは、処理する必要がある残りの単一項目を示します。 .curl ハンドル リソースの数。


curl_multi_remove_handle()

curl バッチ ハンドル リソース内のハンドル リソースを削除します。curl_multi_remove_handle() 関数には 2 つのパラメータがあります。最初のパラメータは、curl バッチ ハンドル リソースを表し、2 番目のパラメータは別のcurl ハンドル リソースを表します。


curl_multi_close()

バッチハンドルリソースを閉じます。


curl_multi_getcontent()

CURLOPT_RETURNTRANSFER が設定されている場合、取得された出力のテキスト ストリームを返します。


curl_multi_info_read()

現在解析されているcurlの関連する送信情報を取得します。


この記事は PHP マルチスレッドの問題について共有されています。ご質問があれば、コメントや提案を残していただければ幸いです。今後、編集者がこのような記事をたくさん紹介していきますので、ぜひご注目ください。

以上がPHPのマルチスレッド処理の問題についての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。