Maison  >  Article  >  développement back-end  >  Concernant les problèmes de traitement multi-thread PHP

Concernant les problèmes de traitement multi-thread PHP

PHPz
PHPzoriginal
2017-11-10 10:36:562773parcourir

Ce qui suit concerne les problèmes de multithreading PHP, l'extension pthreads de PHP et la fonction curl_multi_init. Lorsque vous rencontrez de tels problèmes et que vous ne parvenez pas à les résoudre, regardez comment d'autres les ont résolus.

Tutoriel sur l'installation de pthreads d'extension multi-thread réelle php sous Windows

Adresse de l'extension : http://docs.php.net/manual/zh/ book .pthreads.php
Notes
php5.3 ou supérieur, et il s'agit d'une version thread-safe. Les compilateurs utilisés par Apache et PHP doivent être cohérents.
Si Thread Safety est activé via phpinfo(), cela signifie la version thread-safe.
Vous pouvez connaître le compilateur utilisé en affichant l'élément Compilateur via phpinfo(). Le mien est : MSVC9 (Visual C++ 2008).
Utilisation de l'environnement
Windows XP sp3 32 bits, wampserver2.2d (php5.3.10-vc9 + apache2.2.21-vc9).
1. Télécharger l'extension pthreads
Adresse de téléchargement : http://windows.php.net/downloads/pecl/releases/pthreads
Selon mon environnement, j'ai téléchargé pthreads-2.0.8-5.3-ts -vc9-x86.
2.0.8 représente la version de pthreads.
5.3 représente la version de php.
ts signifie que php nécessite une version thread-safe.
vc9 signifie que php doit être compilé avec le compilateur Visual C++ 2008.
x86 signifie 32 bits

2. Installez l'extension pthreads
Copiez php_pthreads.dll dans le répertoire binphpext. (Mon chemin est D:wampbinphpphp5.3.10ext)
Copiez pthreadVC2.dll dans le répertoire binphp. (Mon chemin est D:wampbinphpphp5.3.10)
Copiez pthreadVC2.dll dans le répertoire C:windowssystem32.
Ouvrez le fichier de configuration php php.ini. Ajoutez l'invite extension=php_pthreads.dll
à la fin ! Les systèmes Windows doivent ajouter le chemin de pthreadVC2.dll à la variable d'environnement PATH. Poste de travail--->bouton droit de la souris--->Propriétés--->Avancé--->Variables d'environnement--->Variables système--->Rechercher le chemin nommé Chemin---> ;Modifier--->Ajoutez le chemin complet de pthreadVC2.dll à la fin de la valeur de la variable (le mien est C:WINDOWSsystem32pthreadVC2.dll).
3. Testez l'extension 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 apparaît lorsque vous exécutez le code ci-dessus, indiquant que l'extension pthreads est installée avec succès !

Ci-joint un exemple simple de 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>";

Les résultats du test sont les suivants :

Temps multithread : 2,8371710777282714844 secondes
Temps de boucle For : 10.941586017608642578 secondes

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;}
  ?>

À propos de curl_multi_init()

De manière générale, pensez à utiliser curl_multi_init () Lorsque le but est de demander plusieurs URL en même temps, plutôt que de les demander une par une, sinon curl_init() sera requis.

Cependant, lors de l'utilisation de curl_multi, vous pouvez rencontrer des phénomènes tels qu'une consommation excessive du processeur et une animation suspendue des pages Web. Vous pouvez découvrir comment résoudre le problème de l'animation suspendue provoquée par curl_multi. 🎜>Résumé des étapes d'utilisation de curl_multi Comme suit :

Étape 1 : Appeler curl_multi_init

Étape 2 : Appeler curl_multi_add_handle dans une boucle

Ce qu'il faut noter dans cette étape, c'est que le deuxième paramètre de curl_multi_add_handle est le sous-handle de curl_init.
Étape 3 : Continuez à appeler curl_multi_exec
Étape 4 : Appelez curl_multi_getcontent en boucle pour obtenir les résultats nécessaires
Étape 5 : Appelez curl_multi_remove_handle et appelez curl_close pour chaque descripteur de mot
Étape 6 : Appelez curl_multi_close

Explication des fonctions de chaque fonction :

curl_multi_init()

Initialiser une ressource de gestion de lots curl.


curl_multi_add_handle()

Ajoute une ressource curl handle distincte à la session curl batch. La fonction curl_multi_add_handle() a deux paramètres. Le premier paramètre représente une ressource de handle de lot curl et le deuxième paramètre représente une ressource de handle curl distincte.


curl_multi_exec()

Analyser un handle de lot curl. La fonction curl_multi_exec() a deux paramètres. Le premier paramètre représente une ressource de handle de lot et le deuxième paramètre est un paramètre de valeur de référence. Les ressources de gestion curl individuelles restantes doivent être traitées.


curl_multi_remove_handle()

Supprimer une ressource de handle dans la ressource de handle de lot curl. La fonction curl_multi_remove_handle() a deux paramètres. Le premier paramètre représente une ressource de handle de lot curl et le deuxième paramètre représente un. ressource de gestion de boucle séparée.


curl_multi_close()

Ferme une ressource de gestion de lots.


curl_multi_getcontent()

Renvoie le flux de texte de la sortie obtenue lorsque CURLOPT_RETURNTRANSFER est défini.


curl_multi_info_read()

Obtenez les informations de transmission pertinentes de la boucle actuellement analysée.


Je partage cet article sur les problèmes de multi-threading PHP. J'espère qu'il sera utile à tout le monde. Si vous avez des questions, vous pouvez laisser vos commentaires ou suggestions. À l'avenir, l'éditeur partagera de nombreux articles sur ce type d'articles, alors veuillez y prêter plus d'attention.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn