(0.8.0)
Cada ejecución representa un solo thread PHP, el thread es creado (e inicializado) durante la construcción. El thread espera luego a que se programen tareas: las tareas programadas serán ejecutadas FIFO y luego el thread volverá a esperar hasta que se programen otras tareas, o hasta que sea cerrado, eliminado o destruido por las reglas de ámbito normales de los objetos PHP.
Cuando una ejecución es destruida por las reglas de ámbito normales de los objetos PHP, primero ejecutará todas las tareas que han sido programadas, y bloqueará durante este tiempo.
Cuando se crea una nueva ejecución, no comparte código con el thread (o el proceso) que la creó. Esto significa que no tiene las mismas clases y funciones cargadas, ni el mismo cargador automático definido. En algunos casos, una ejecución muy ligera es deseable porque las tareas que serán programadas no necesitan acceder al código del thread padre. En los casos en que las tareas necesitan acceder al mismo código, basta con definir un cargador automático como amortiguación.
Nota:
La precarga puede ser utilizada en conjunción con parallel, en este caso el código precargado está disponible sin amortiguación.
basic-multithreading-test.php
<?php
use parallel\Runtime;
use parallel\Channel;
$test = "this var is not accesible in a thread";
// this function will be the threads
$thread_function = function (int $id, Channel $ch) {
// delay the first thread to simulate better multithreading
// second thread always finishes first
$sleep = ($id == 2) ? 1 : 2;
sleep($sleep);
// print thread id
// so it's clear second thread goes first
// and also you can make sure multithreading is working
var_dump("thread $id sleep $sleep");
// try to capture globals, but it's not possible
echo '$GLOBALS["test"] = ';
@var_dump($GLOBALS["test"]);
// the only way to share data is between channels
$ch->send($sleep);
};
try {
// each runtime represents a thread
$r1 = new Runtime();
$r2 = new Runtime();
// channel where the date will be sharead
$ch1 = new Channel();
// args that will be sent to $thread_function
$args = array();
$args[0] = null;
$args[1] = $ch1;
// running thread 1
$args[0] = 1;
$r1->run($thread_function, $args);
// running thread 2
$args[0] = 2;
$r2->run($thread_function, $args);
// receive data from channel
$x = $ch1->recv();
$y = $ch1->recv();
// close channel
$ch1->close();
echo "\nData received by the channel: $x and $y";
} catch (Error $err) {
echo "\nError:", $err->getMessage();
} catch (Exception $e) {
echo "\nException:", $e->getMessage();
}<?php
// make sure that is really parallel execution (showcase2).
// Then you use echo within task-function there is a real chance that the application will hang.
// We should control Futures to avoid this behaviour.
// You will get different output on each execution.
use parallel\{Future, Runtime};
const THREADS_COUNT = 10;
const THREADS_I_MAX = 100;
// executed within thread
$task = static function (int $i, int $to): void {
echo "[enter$i]";
for ($j = 0; $j < $to; $j++) {
echo $i;
}
echo "[exit$i]";
};
// creating a few threads
$runtimeList = [];
for ($i = 0; $i < THREADS_COUNT; $i++) {
$runtimeList[] = new Runtime();
}
// run all threads
$futureList = [];
foreach ($runtimeList as $i => $runtime) {
echo "[run$i]";
$futureList[] = $runtime->run($task, [$i, THREADS_I_MAX]);
}
// waiting until all threads are done
// if you delete code bellow then your script will hang
do {
usleep(1);
$allDone = array_reduce(
$futureList,
function (bool $c, Future $future): bool {
return $c && $future->done();
},
true
);
} while (false === $allDone);
echo "done\n";new Runtime() will reset some basic (before number 10+-) Linux signal.
If you already set handle of signal by pcntl_signal function - you need do it again<?php
// make sure that is really parallel execution
// you will get different output on each script run
use parallel\{Channel, Runtime};
const THREADS_COUNT = 5;
const THREADS_I_MAX = 10;
$ch = new Channel();
// executed within thread
$task = static function (Channel $ch, int $i, int $to): void {
echo "[enter: $i]\n";
for ($j = 0; $j < $to; $j++) {
$ch->send($i);
}
echo "[exit: $i]\n";
};
// creating a few threads
$runtimeList = [];
for ($i = 0; $i < THREADS_COUNT; $i++) {
$runtimeList[] = new Runtime();
}
// run all threads
foreach ($runtimeList as $i => $runtime) {
echo "[run: $i]\n";
$runtime->run($task, [$ch, $i, THREADS_I_MAX]);
}
// reading messages from channel
$queue = '';
for ($i = 0; $i < THREADS_COUNT * THREADS_I_MAX; $i++) {
$queue .= $ch->recv();
}
$ch->close();
echo $queue . PHP_EOL;