Параллельные задачи
Запускайте несколько независимых задач одновременно на разных ядрах CPU, затем дождитесь их всех. Поскольку процессы не делят память, результаты возвращаются через файлы или базу данных, а не через общие переменные (см. модель работы).
Запустить много, дождаться всех
Сохраните ссылку на каждый Thread, запустите их, затем вызовите join() для каждого:
<?php
require 'vendor/autoload.php';
use Flytachi\Winter\Thread\Thread;
$threads = [];
foreach (range(1, 8) as $reportId) {
$thread = new Thread(new ReportGenerator($reportId), 'Reports', 'ReportGenerator', "r-{$reportId}");
$thread->start();
$threads[] = $thread;
}
// Дожидаемся всех; считаем неудачи по коду выхода
$failed = 0;
foreach ($threads as $thread) {
if ($thread->join() !== 0) {
$failed++;
}
}
echo "Done. {$failed} failed.\n";Ограничьте параллелизм пулом
Запускать по процессу на элемент нормально для горстки задач. Для сотен — ограничьте число одновременно работающих, чтобы не перегрузить машину:
<?php
require 'vendor/autoload.php';
use Flytachi\Winter\Thread\Thread;
$queue = range(1, 200);
$maxConcurrent = 4;
$running = [];
while ($queue || $running) {
// Добираем до лимита параллелизма
while (count($running) < $maxConcurrent && $queue) {
$id = array_shift($queue);
$thread = new Thread(new ReportGenerator($id), 'Reports', 'ReportGenerator', "r-{$id}");
$thread->start();
$running[] = $thread;
}
// Убираем завершившиеся
foreach ($running as $i => $thread) {
if (!$thread->isAlive()) {
$thread->join(); // читаем код выхода, освобождаем процесс
unset($running[$i]);
}
}
$running = array_values($running);
usleep(50_000); // 50 мс; избегаем busy-loop
}Выберите разумный лимит
Хорошая отправная точка — число ядер CPU для вычислительных задач или больше для I/O-задач (ожидание сети). Измеряйте, а не гадайте.
Собирайте результаты
Поскольку дочерние процессы не могут вернуть объекты, пусть каждая задача пишет свой
результат туда, откуда родитель прочитает его после join():
// Внутри run(): пишем результат, который заберёт родитель
file_put_contents("/tmp/report-{$this->reportId}.json", json_encode($rows));
// В родителе, после join():
$result = json_decode(file_get_contents("/tmp/report-{$reportId}.json"), true);Код выхода из join() — самый дешёвый канал результата: используйте его для простого
«успех/неудача», а файлы или базу данных приберегите для настоящих payload’ов.
Связанное
- Обработчик очереди — запуск задач и передача аргументов
- Корректное завершение — таймауты и отмена
- Справочник API —
isAlive(),join()