International PHP Conference Berlin 2025

A classe parallel\Runtime

(0.8.0)

Runtime Objects

Cada tempo de execução representa um único thread PHP, o thread é criado (e inicializado) durante a construção. O thread então espera que as tarefas sejam agendadas: As tarefas agendadas serão executadas FIFO e então o thread continuará esperando até que mais tarefas sejam agendadas ou seja fechado, eliminado ou destruído pelas regras normais de escopo dos objetos PHP.

Aviso

Quando um tempo de execução é destruído pelas regras normais de escopo de objetos PHP, ele primeiro executará todas as tarefas que foram agendadas e bloqueará ao fazê-lo.

Bootstrapping em tempo de execução

Quando um novo tempo de execução é criado, ele não compartilha código com o thread (ou processo) que o criou. Isso significa que ele não possui as mesmas classes e funções carregadas, nem o mesmo conjunto de autoloader. Em alguns casos, um tempo de execução muito leve é desejável porque as tarefas que serão agendadas não precisam de acesso ao código no thread pai. Nos casos em que as tarefas precisam acessar o mesmo código, basta definir um autoloader como bootstrap.

Nota:

preloading pode ser usado em conjunto com o parallel; neste caso, o código pré-carregado está disponível sem inicialização

Resumo da classe

final class parallel\Runtime {
/* Create */
public __construct()
public __construct(string $bootstrap)
/* Execute */
public run(Closure $task): ?Future
public run(Closure $task, array $argv): ?Future
/* Join */
public close(): void
public kill(): void
}

Índice

adicione uma nota

Notas Enviadas por Usuários (em inglês) 4 notes

up
20
Luciano Vettoretti
5 years ago
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();
}
up
5
gam6itko
3 years ago
<?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";
up
0
Mikhail Streltsov (admin at my-fantasy dot ru)
1 year ago
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
up
0
gam6itko
3 years ago
<?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;
To Top