PHP 8.1.28 Released!

Класс parallel\Runtime

(0.8.0)

Объекты во временя выполнения

Каждая среда выполнения представляет собой один поток PHP, поток создаётся (и загружается) при создании. Затем поток ожидает, пока задачи будут запланированы: запланированные задачи будут выполняться FIFO, а затем поток возобновит ожидание, пока не будут запланированы другие задачи или пока он не будет закрыт, убит или уничтожен в соответствии с обычными правилами области видимости объектов PHP.

Внимание

Когда среда выполнения уничтожается обычными правилами области видимости объектов PHP, она сначала выполняет все запланированные задачи и при этом блокирует добавление новых.

Начальная загрузка во время выполнения

Когда создаётся новая среда выполнения, она не разделяет код с потоком (или процессом), который её создал. Это означает, что в нём не загружены те же классы и функции, а также не установлен один и тот же автозагрузчик. В некоторых случаях желательна очень лёгкая среда выполнения, потому что задачи, которые будут запланированы, не нуждаются в доступе к коду в родительском потоке. В тех случаях, когда задачам нужен доступ к одному и тому же коду, достаточно установить автозагрузчик в качестве начальной загрузки.

Замечание:

Предварительная загрузка может использоваться вместе с параллельной, в этом случае предварительно загруженный код доступен без начальной загрузки.

Обзор классов

final class parallel\Runtime {
/* Создание */
public __construct()
public __construct(string $bootstrap)
/* Выполнение */
public run(Closure $task): ?Future
public run(Closure $task, array $argv): ?Future
/* Присоединение */
public close(): void
public kill(): void
}

Содержание

add a note

User Contributed Notes 4 notes

up
21
Luciano Vettoretti
4 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
4
gam6itko
2 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)
8 months 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
2 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