Heim  >  Artikel  >  Backend-Entwicklung  >  So implementieren Sie Multithreading in PHP

So implementieren Sie Multithreading in PHP

墨辰丷
墨辰丷Original
2018-06-01 09:27:535164Durchsuche

Multithreading ist eine sehr gute Sache in Java. Viele Freunde sagen, dass PHP-Multithreading in PHP nicht verwendet werden kann. In diesem Artikel werden zwei Implementierungsmethoden für Multithreading vorgestellt. Wenn Sie interessiert sind, können Studierende einen Blick darauf werfen.

Unterstützt PHP selbst Multithreading? Wir können jedoch auch andere Methoden verwenden, um Multithreading zu erreichen, z. B. Shell-Dienste, z. B. Webserver. In diesem Artikel werden wir darüber sprechen, wie diese beiden implementiert werden Methoden. Freunde in Not können kommen und sich darauf beziehen.

Multithreading ist eine sehr gute Sache in Java. Viele Freunde sagen, dass PHP-Multithreading in der Tat eine falsche Aussage ist bezieht sich auf die fsockopen-Funktion. Nachfolgend stellen wir den spezifischen Implementierungsprogrammcode vor.

Wenn jemand Parallelitätsfunktionen implementieren möchte, denkt er normalerweise an die Verwendung von Fork- oder Spawn-Threads. Wenn er jedoch feststellt, dass PHP kein Multithreading unterstützt, ändert er möglicherweise seine Meinung und verwendet etwas, das Multithreading unterstützt nicht gut genug Sprache, wie zum Beispiel Perl.

Tatsächlich müssen Sie in den meisten Fällen weder Fork noch Thread verwenden und erzielen eine bessere Leistung als mit Fork oder Thread.

Angenommen, Sie möchten einen Dienst erstellen, um n laufende Server zu überprüfen, um sicherzustellen, dass sie noch normal funktionieren. Sie könnten Code wie diesen schreiben:

Code wie diesen:

<?php
$hosts = array("host1.sample.com", "host2.sample.com", "host3.sample.com");
$timeout = 15;
$status = array();
foreach ($hosts as $host) {
$errno = 0;
 $errstr = "";
 $s = fsockopen($host, 80, $errno, $errstr, $timeout);
 if ($s) {
 $status[$host] = "Connectedn";
 fwrite($s, "HEAD / HTTP/1.0rnHost: $hostrnrn");
 do {
 $data = fread($s, 8192);
 if (strlen($data) == 0) {
 break;
 }
 $status[$host] .= $data;
 } while (true);
 fclose($s);
 } else {
 $status[$host] = "Connection failed: $errno $errstrn";
 }
}
print_r($status);
?>

it This Funktioniert gut, aber die Erweiterung dieses Codes zur Verwaltung einer großen Anzahl von Servern würde lange dauern, bis fsockopen() den Hostnamen analysiert und eine erfolgreiche Verbindung hergestellt hat (oder $timeout-Sekunden verzögern).

Wir müssen diesen Code also aufgeben; wir können eine asynchrone Verbindung herstellen – wir müssen nicht warten, bis fsockopen den Verbindungsstatus zurückgibt. PHP muss den Hostnamen noch auflösen (daher ist es sinnvoller, die IP direkt zu verwenden), aber er kehrt sofort nach dem Öffnen einer Verbindung zurück und wir können uns dann mit dem nächsten Server verbinden.

In PHP5 gibt es zwei Möglichkeiten, dies zu erreichen: Sie können die neue Funktion stream_socket_client() verwenden, um fsocketopen() direkt zu ersetzen. Bei Versionen vor PHP5 müssen Sie es selbst tun und die Sockets-Erweiterung verwenden, um das Problem zu lösen.

Hier ist die Lösung in PHP5:

Es läuft gut, aber nachdem fsockopen() den Hostnamen analysiert und einen erfolgreichen Skalierungscode erstellt hat Die Verwaltung einer großen Anzahl von Servern würde lange dauern, bis eine Verbindung hergestellt wird (oder sich $timeout Sekunden verzögern).

Wir müssen diesen Code also aufgeben; wir können eine asynchrone Verbindung herstellen – wir müssen nicht warten, bis fsockopen den Verbindungsstatus zurückgibt. PHP muss den Hostnamen noch auflösen (daher ist es sinnvoller, die IP direkt zu verwenden), aber er kehrt sofort nach dem Öffnen einer Verbindung zurück und wir können uns dann mit dem nächsten Server verbinden.

In PHP5 gibt es zwei Möglichkeiten, dies zu erreichen: Sie können die neue Funktion stream_socket_client() verwenden, um fsocketopen() direkt zu ersetzen. Bei Versionen vor PHP5 müssen Sie es selbst tun und die Sockets-Erweiterung verwenden, um das Problem zu lösen.

Der Code lautet wie folgt:

<?php
$hosts = array("host1.sample.com", "host2.sample.com", "host3.sample.com");
$timeout = 15;
$status = array();
$sockets = array();
/* Initiate connections to all the hosts simultaneously */
foreach ($hosts as $id => $host) {
 $s = stream_socket_client("
$
$host:80", $errno, $errstr, $timeout,
 STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT);
 if ($s) {
 $sockets[$id] = $s;
 $status[$id] = "in progress";
 } else {
 $status[$id] = "failed, $errno $errstr";
 }
}
/* Now, wait for the results to come back in */
while (count($sockets)) {
 $read = $write = $sockets;
 /* This is the magic function - explained below */
 $n = stream_select($read, $write, $e = null, $timeout);
 if ($n > 0) {
 /* readable sockets either have data for us, or are failed
 * connection attempts */
 foreach ($read as $r) {
  $id = array_search($r, $sockets);
  $data = fread($r, 8192);
  if (strlen($data) == 0) {
 if ($status[$id] == "in progress") {
 $status[$id] = "failed to connect";
 }
 fclose($r);
 unset($sockets[$id]);
  } else {
 $status[$id] .= $data;
  }
 }
 /* writeable sockets can accept an HTTP request */
 foreach ($write as $w) {
 $id = array_search($w, $sockets);
 fwrite($w, "HEAD / HTTP/1.0rnHost: "
 . $hosts[$id] . "rnrn");
 $status[$id] = "waiting for response";
 }
 } else {
 /* timed out waiting; assume that all hosts associated
 * with $sockets are faulty */
 foreach ($sockets as $id => $s) {
 $status[$id] = "timed out " . $status[$id];
 }
 break;
 }
}
foreach ($hosts as $id => $host) {
 echo "Host: $hostn";
 echo "Status: " . $status[$id] . "nn";
} 
?>

Wir verwenden stream_select() zum Warten für die durch das Sockets-Ereignis geöffnete Verbindung. stream_select() ruft die Funktion select(2) des Systems auf, um zu funktionieren: Die ersten drei Parameter sind die Arrays von Streams, die Sie verwenden möchten, Sie können sie lesen, schreiben und Ausnahmen davon erhalten (jeweils für die drei Parameter). stream_select() kann auf das Eintreten eines Ereignisses warten, indem der Parameter $timeout (Sekunden) festgelegt wird. Wenn das Ereignis eintritt, werden die entsprechenden Socket-Daten in die von Ihnen übergebenen Parameter geschrieben.

Das Folgende ist die Implementierung von Versionen nach PHP 4.1.0. Wenn Sie beim Kompilieren von PHP Sockets (ext/sockets) unterstützt haben, können Sie ähnlichen Code wie oben verwenden, müssen ihn nur ändern oben Die Funktionen von Streams/Dateisystemfunktionen werden mithilfe von Ext/Sockets-Funktionen implementiert. Der Hauptunterschied besteht darin, dass wir anstelle von stream_socket_client() die folgende Funktion verwenden, um die Verbindung herzustellen:

Der Code lautet wie folgt:

<?php
// This value is correct for Linux, other systems have other values
define(&#39;EINPROGRESS&#39;, 115);
function non_blocking_connect($host, $port, &$errno, &$errstr, $timeout) {
 $ip = gethostbyname($host);
 $s = socket_create(AF_INET, SOCK_STREAM, 0);
 if (socket_set_nonblock($s)) {
 $r = @socket_connect($s, $ip, $port);
 if ($r || socket_last_error() == EINPROGRESS) {
 $errno = EINPROGRESS;
 return $s;
 }
 }
 $errno = socket_last_error($s);
 $errstr = socket_strerror($errno);
 socket_close($s);
 return false;
}
?>

Jetzt verwenden Sie socket_select(), um stream_select() zu ersetzen, verwenden Sie socket_read(), um fread() zu ersetzen, verwenden Sie socket_write(), um fwrite() zu ersetzen, verwenden Sie socket_close(), um zu ersetzen fclose() und Sie können Scripted ausführen!

Der Fortschritt von PHP5 besteht darin, dass Sie stream_select() verwenden können, um fast alle Streams zu verarbeiten. Beispielsweise können Sie damit Tastatureingaben über include STDIN empfangen und in einem Array speichern Sie können die Daten auch über proc_open() in der geöffneten Pipe empfangen.

Lassen Sie mich eine PHP-Multithread-Klasse teilen

Der Code lautet wie folgt:

class thread {
 
 var $hooks = array();
 var $args = array();
 
 function thread() {
 }
 
 function addthread($func)
 {
  $args = array_slice(func_get_args(), 1);
  $this->hooks[] = $func;
  $this->args[] = $args;
  return true;
 }
 
 function runthread()
 {
  if(isset($_GET[&#39;flag&#39;]))
  {
   $flag = intval($_GET[&#39;flag&#39;]);
  }
  if($flag || $flag === 0)
  {
   call_user_func_array($this->hooks[$flag], $this->args[$flag]);
  }
  else
  {
   for($i = 0, $size = count($this->hooks); $i < $size; $i++)
   {
    $fp=fsockopen($_SERVER[&#39;HTTP_HOST&#39;],$_SERVER[&#39;SERVER_PORT&#39;]);
    if($fp)
    {
     $out = "GET {$_SERVER[&#39;PHP_SELF&#39;]}?flag=$i HTTP/1.1rn";
     $out .= "Host: {$_SERVER[&#39;HTTP_HOST&#39;]}rn";
     $out .= "Connection: Closernrn";
     fputs($fp,$out);
     fclose($fp);
    }
   }
  }
 }
}

Zusammenfassung: Das Obige ist der gesamte Inhalt dieses Artikels, ich hoffe, dass er für das Studium aller hilfreich sein wird.

Verwandte Empfehlungen:

phpUnternehmenszahlung per WeChat-Zahlung

php Gleichzeitige Sperrfallanalyse

phpDetaillierte Erläuterung von Beispielen für Sortieralgorithmen

Das obige ist der detaillierte Inhalt vonSo implementieren Sie Multithreading in PHP. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn