2024 年日本 PHP 研討會

parallel\Runtime 類別

(0.8.0)

Runtime 物件

每個 Runtime 代表一個單獨的 PHP 執行緒,該執行緒在建構時建立(並啟動)。然後,該執行緒會等待排程任務:已排程的任務將以 FIFO 方式執行,然後執行緒將繼續等待,直到排程更多任務,或依 PHP 物件的正常作用域規則關閉、終止或銷毀。

警告

當 Runtime 依 PHP 物件的正常作用域規則銷毀時,它會先執行所有已排程的任務,並在此期間阻塞。

Runtime 啟動

當建立新的運行時 (runtime) 時,它不會與建立它的線程(或進程)共享程式碼。這意味著它沒有載入相同的類別和函數,也沒有設定相同的自動載入器。在某些情況下,需要一個非常輕量級的運行時,因為將要調度的任務不需要訪問父線程中的程式碼。在任務確實需要訪問相同程式碼的情況下,只需將自動載入器設定為啟動程式 (bootstrap) 即可。

注意事項:

預載入可以與 parallel 並用,在這種情況下,預載入的程式碼無需啟動程式即可使用。

類別概要

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
}

目錄

新增註解

使用者貢獻的註解 4 則註解

Luciano Vettoretti
5 年前
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();
}
gam6itko
3 年前
<?php

// 確保真的是平行執行 (showcase2)。
// 然後,如果您在任務函式中使用 echo,應用程式很有可能會掛起。
// 我們應該控制 Futures 以避免這種情況。
// 每次執行都會得到不同的輸出。

use parallel\{Future, Runtime};

const
THREADS_COUNT = 10;
const
THREADS_I_MAX = 100;

// 在執行緒內執行
$task = static function (int $i, int $to): void {
echo
"[enter$i]";
for (
$j = 0; $j < $to; $j++) {
echo
$i;
}
echo
"[exit$i]";
};

// 建立幾個執行緒
$runtimeList = [];
for (
$i = 0; $i < THREADS_COUNT; $i++) {
$runtimeList[] = new Runtime();
}
// 執行所有執行緒
$futureList = [];
foreach (
$runtimeList as $i => $runtime) {
echo
"[run$i]";
$futureList[] = $runtime->run($task, [$i, THREADS_I_MAX]);
}

// 等待所有執行緒完成
// 如果您刪除以下程式碼,您的腳本將會掛起
do {
usleep(1);
$allDone = array_reduce(
$futureList,
function (
bool $c, Future $future): bool {
return
$c && $future->done();
},
true
);
} while (
false === $allDone);
echo
"done\n";
Mikhail Streltsov (my-fantasy.ru 的管理員)
1 年前
新的 Runtime() 會重置一些基本的 (10 以下) Linux 信號。

如果您已經使用 pcntl_signal 函式設定了信號處理程序,則需要再次執行。
gam6itko
3 年前
<?php

// 確保確實是平行執行
// 每次執行腳本都會得到不同的輸出

use parallel\{Channel, Runtime};

const
THREADS_COUNT = 5;
const
THREADS_I_MAX = 10;

$ch = new Channel();

// 在線程內執行
$task = static function (Channel $ch, int $i, int $to): void {
echo
"[進入: $i]\n";
for (
$j = 0; $j < $to; $j++) {
$ch->send($i);
}
echo
"[離開: $i]\n";
};

// 建立幾個線程
$runtimeList = [];
for (
$i = 0; $i < THREADS_COUNT; $i++) {
$runtimeList[] = new Runtime();
}
// 執行所有線程
foreach ($runtimeList as $i => $runtime) {
echo
"[執行: $i]\n";
$runtime->run($task, [$ch, $i, THREADS_I_MAX]);
}

// 從通道讀取訊息
$queue = '';
for (
$i = 0; $i < THREADS_COUNT * THREADS_I_MAX; $i++) {
$queue .= $ch->recv();
}
$ch->close();

echo
$queue . PHP_EOL;
To Top