502 Stimmen

Wie kann man Multi-Threading in PHP-Anwendungen nutzen?

Gibt es eine realistische Möglichkeit, ein Multi-Thread-Modell in PHP zu implementieren, sei es real oder nur simuliert. Vor einiger Zeit wurde vorgeschlagen, dass man das Betriebssystem zwingen könnte, eine weitere Instanz der ausführbaren PHP-Datei zu laden und andere gleichzeitige Prozesse zu bearbeiten.

Das Problem dabei ist, dass die PHP-Instanz nach Beendigung der Ausführung des PHP-Codes im Speicher verbleibt, da es keine Möglichkeit gibt, sie von PHP aus zu beenden. Wenn Sie also mehrere Threads simulieren, können Sie sich vorstellen, was passieren wird. Ich bin also immer noch auf der Suche nach einer Möglichkeit, wie Multi-Threading innerhalb von PHP effektiv durchgeführt oder simuliert werden kann. Hat jemand eine Idee?

506voto

Baba Punkte 91769

Multi-threading ist in php möglich

Ja, Sie können Multithreading in PHP mit pthreads

Desde die PHP-Dokumentation :

pthreads ist ein objektorientiertes API, das alle Werkzeuge bereitstellt, die für Multi-Threading in PHP benötigt werden. PHP-Anwendungen können Threads, Workers und Threaded-Objekte erstellen, lesen, schreiben, ausführen und mit ihnen synchronisieren.

Warnung : Die pthreads-Erweiterung kann nicht in einer Webserver-Umgebung verwendet werden. Threading in PHP sollte daher nur für CLI-basierte Anwendungen verwendet werden.

Einfacher Test

#!/usr/bin/php
<?php
class AsyncOperation extends Thread {

    public function __construct($arg) {
        $this->arg = $arg;
    }

    public function run() {
        if ($this->arg) {
            $sleep = mt_rand(1, 10);
            printf('%s: %s  -start -sleeps %d' . "\n", date("g:i:sa"), $this->arg, $sleep);
            sleep($sleep);
            printf('%s: %s  -finish' . "\n", date("g:i:sa"), $this->arg);
        }
    }
}

// Create a array
$stack = array();

//Initiate Multiple Thread
foreach ( range("A", "D") as $i ) {
    $stack[] = new AsyncOperation($i);
}

// Start The Threads
foreach ( $stack as $t ) {
    $t->start();
}

?>

Erster Lauf

12:00:06pm:     A  -start -sleeps 5
12:00:06pm:     B  -start -sleeps 3
12:00:06pm:     C  -start -sleeps 10
12:00:06pm:     D  -start -sleeps 2
12:00:08pm:     D  -finish
12:00:09pm:     B  -finish
12:00:11pm:     A  -finish
12:00:16pm:     C  -finish

Zweiter Durchlauf

12:01:36pm:     A  -start -sleeps 6
12:01:36pm:     B  -start -sleeps 1
12:01:36pm:     C  -start -sleeps 2
12:01:36pm:     D  -start -sleeps 1
12:01:37pm:     B  -finish
12:01:37pm:     D  -finish
12:01:38pm:     C  -finish
12:01:42pm:     A  -finish

Beispiel aus der Praxis

error_reporting(E_ALL);
class AsyncWebRequest extends Thread {
    public $url;
    public $data;

    public function __construct($url) {
        $this->url = $url;
    }

    public function run() {
        if (($url = $this->url)) {
            /*
             * If a large amount of data is being requested, you might want to
             * fsockopen and read using usleep in between reads
             */
            $this->data = file_get_contents($url);
        } else
            printf("Thread #%lu was not provided a URL\n", $this->getThreadId());
    }
}

$t = microtime(true);
$g = new AsyncWebRequest(sprintf("http://www.google.com/?q=%s", rand() * 10));
/* starting synchronization */
if ($g->start()) {
    printf("Request took %f seconds to start ", microtime(true) - $t);
    while ( $g->isRunning() ) {
        echo ".";
        usleep(100);
    }
    if ($g->join()) {
        printf(" and %f seconds to finish receiving %d bytes\n", microtime(true) - $t, strlen($g->data));
    } else
        printf(" and %f seconds to finish, request failed\n", microtime(true) - $t);
}

65voto

masterb Punkte 653

Warum benutzen Sie nicht popen ?

for ($i=0; $i<10; $i++) {
    // open ten processes
    for ($j = 0; $j < 10; $j++) {
        $pipe[$j] = popen('script2.php', 'w');
    }

    // wait for them to finish
    for ($j = 0; $j < 10; ++$j) {
        pclose($pipe[$j]);
    }
}

29voto

Ricardo Punkte 1

Threading ist in Standard-PHP nicht verfügbar, aber nebenläufige Programmierung ist möglich, indem HTTP-Anfragen als asynchrone Aufrufe verwendet werden.

Wenn die Timeout-Einstellung von curl auf 1 gesetzt ist und die gleiche session_id für die Prozesse verwendet wird, die miteinander verbunden werden sollen, können Sie mit Sitzungsvariablen kommunizieren, wie in meinem Beispiel unten. Mit dieser Methode können Sie sogar Ihren Browser schließen und der gleichzeitige Prozess existiert immer noch auf dem Server.

Vergessen Sie nicht, die korrekte Sitzungs-ID wie folgt zu überprüfen:

[http://localhost/test/verifysession.php?sessionid=\[die](http://localhost/test/verifysession.php?sessionid=[the) richtige ID]

startprocess.php

$request = "http://localhost/test/process1.php?sessionid=".$_REQUEST["PHPSESSID"];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_exec($ch);
curl_close($ch);
echo $_REQUEST["PHPSESSID"];

process1.php

set_time_limit(0);

if ($_REQUEST["sessionid"])
   session_id($_REQUEST["sessionid"]);

function checkclose()
{
   global $_SESSION;
   if ($_SESSION["closesession"])
   {
       unset($_SESSION["closesession"]);
       die();
   }
}

while(!$close)
{
   session_start();
   $_SESSION["test"] = rand();
   checkclose();
   session_write_close();
   sleep(5);
}

verifysession.php

if ($_REQUEST["sessionid"])
    session_id($_REQUEST["sessionid"]);

session_start();
var_dump($_SESSION);

closeprocess.php

if ($_REQUEST["sessionid"])
    session_id($_REQUEST["sessionid"]);

session_start();
$_SESSION["closesession"] = true;
var_dump($_SESSION);

17voto

J.D. Fitz.Gerald Punkte 2897

Sie können zwar keine Threads erstellen, aber Sie haben ein gewisses Maß an Prozesskontrolle in PHP. Die beiden Funktionssätze, die hier nützlich sind, sind:

Funktionen zur Prozesssteuerung http://www.php.net/manual/en/ref.pcntl.php

POSIX-Funktionen http://www.php.net/manual/en/ref.posix.php

Sie können Ihren Prozess mit pcntl_fork forken - und erhalten die PID des Kindprozesses zurück. Dann können Sie posix_kill benutzen, um diese PID zu entsorgen.

Das heißt, wenn Sie einen Elternprozess beenden, sollte ein Signal an den Kindprozess gesendet werden, das ihn auffordert, zu sterben. Wenn php selbst dies nicht erkennt, könnten Sie eine Funktion registrieren, die dies verwaltet und einen sauberen Abbruch mit pcntl_signal durchführen.

13voto

pinkal vansia Punkte 9940

Die Verwendung von Threads wird durch die PECL-Erweiterung pthreads ermöglicht

http://www.php.net/manual/en/book.pthreads.php

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X