Start · Sprachen · PHP · Referenz · parallel\run

parallel\run

Funktion

Führt eine <code>Closure</code> in einem neuen parallelen Thread aus und gibt ein <code>Future</code>-Objekt zur Ergebnisabholung zurück.

seit PHP 1.0.0 Kategorie: misc

Signatur

parallel\run(Closure $task, array $argv = []): \parallel\Future

Beschreibung

parallel\run() ist die zentrale Funktion der PHP-Erweiterung parallel und ermöglicht echte Parallelverarbeitung in PHP durch den Einsatz von POSIX-Threads (pthreads). Die übergebene Closure wird in einem separaten Thread ausgeführt, sodass der aufrufende Code währenddessen weiterläuft.

Der Rückgabewert ist ein \parallel\Future-Objekt. Über dessen Methode value() kann der Aufrufer auf das Ergebnis des Threads warten (blockierendes Join). Wirft die Task-Closure eine Exception, wird diese beim Aufruf von value() erneut ausgelöst.

Optionale Argumente für die Closure werden als zweiter Parameter als array übergeben. Innerhalb der Task-Closure gelten strenge Einschränkungen: Es dürfen keine Variablen aus dem äußeren Scope per use gebunden werden, die nicht thread-sicher sind. Erlaubt sind primitive Typen, parallel\Channel-Objekte und als unveränderlich markierte Werte.

Die Funktion eignet sich besonders für CPU-intensive Berechnungen (z. B. Bildverarbeitung, Kryptographie, Datenaggregation), die parallel zum Haupt-Thread ausgeführt werden sollen, um die Antwortzeit zu reduzieren.

Parameter

Name Typ Default Beschreibung
$task Pflicht Closure Die Closure, die in einem separaten Thread ausgeführt werden soll. Sie darf keine nicht-thread-sicheren Variablen per use binden.
$argv array [] Optionales Array mit Argumenten, die als Parameter an die $task-Closure übergeben werden.

Rückgabewert

Typ
\parallel\Future
Beschreibung
Gibt ein \parallel\Future-Objekt zurück, über dessen Methode value() auf das Ergebnis des Threads gewartet werden kann. Wirft die Task eine Exception, wird diese bei value() re-thrown.

Beispiele

Einfache parallele Berechnung

<?php
use parallel\Runtime;

// parallel\run() ohne expliziten Runtime-Kontext
$future = \parallel\run(function (int $n): int {
    $sum = 0;
    for ($i = 1; $i <= $n; $i++) {
        $sum += $i;
    }
    return $sum;
}, [1000]);

// Hier kann der Haupt-Thread weiterarbeiten...
echo "Warte auf Ergebnis...\n";

// Ergebnis abholen (blockiert bis der Thread fertig ist)
$result = $future->value();
echo "Summe 1 bis 1000: {$result}\n";
Warte auf Ergebnis... Summe 1 bis 1000: 500500

Mehrere Tasks parallel ausführen

<?php
$urls = [
    'https://example.com',
    'https://example.org',
    'https://example.net',
];

$futures = [];
foreach ($urls as $url) {
    $futures[$url] = \parallel\run(function (string $url): int {
        // Simuliert eine netzwerklastige Operation
        $context = stream_context_create(['http' => ['timeout' => 5]]);
        $content = @file_get_contents($url, false, $context);
        return $content !== false ? strlen($content) : 0;
    }, [$url]);
}

// Alle Ergebnisse einsammeln
foreach ($futures as $url => $future) {
    try {
        $bytes = $future->value();
        echo "{$url}: {$bytes} Bytes\n";
    } catch (\parallel\Future\Error\Killed $e) {
        echo "{$url}: Thread wurde abgebrochen\n";
    } catch (\Throwable $e) {
        echo "{$url}: Fehler – {$e->getMessage()}\n";
    }
}
https://example.com: 1256 Bytes https://example.org: 1256 Bytes https://example.net: 1256 Bytes

// Wichtig · Fallstricke

Voraussetzungen: Die parallel-Erweiterung erfordert PHP, das mit ZTS (Zend Thread Safety) kompiliert wurde (--enable-zts). Standard-PHP-Builds sind häufig nicht ZTS-fähig.

Einschränkungen für Task-Closures: Innerhalb der Closure sind folgende Konstrukte nicht erlaubt: use von nicht-thread-sicheren Objekten, statische Closures, Referenzen auf externe Ressourcen (z. B. Datenbankverbindungen, Streams). Verstöße führen zu einem \parallel\Runtime\Error\IllegalInstruction.

Exception-Handling: Exceptions, die innerhalb eines Threads auftreten, werden nicht sofort geworfen, sondern erst beim Aufruf von $future->value(). Der Aufruf sollte daher stets in einem try/catch-Block erfolgen.

Ressourcen: Jeder parallel\run()-Aufruf erzeugt einen neuen Thread. Bei sehr vielen parallelen Tasks sollte stattdessen parallel\Runtime mit einem Worker-Pool verwendet werden, um den Overhead zu begrenzen.