я использую Pool
объект в PHP pthread
и сделал следующий тестовый скрипт, чтобы увидеть, как пул должен работать. Я подумал, что пул должен делать, чтобы получить заданное количество задач, открыть максимум x
количество работников и назначьте им задачи, и, как только работник завершит выполнение задачи, если доступно больше задач, назначьте этому работнику новую задачу.
Приведенный ниже пример и приведенное выше предположение:
class Work extends Threaded {
public $id;
public function __construct($id) {
$this->id = $id;
}
public function run() {
if ($this->id == 0) {
sleep(3);
echo $this->id . " is ready\n";
return;
} else {
echo $this->id . " is ready\n";
return;
}
}
}
$pool = new Pool(2, 'Worker', []);
for ($i=0; $i<4; $i++) $pool->submit(new Work($i));
while ($pool->collect());
$pool->shutdown();
Я ожидал, что этот скрипт выведет следующую информацию:
1 готово
2 готово
3 готово
0 готово
потому что, по сути, есть 2 работника, и из-за sleep
Когда первый рабочий наткнулся, задание 1, 2, 3 должно быть выполнено вторым рабочим.
Вместо этого я получаю вывод:
1 готово
3 готово
0 готово
2 готово
Понятно, что работник 1 получает задание 0 и задание 2 сразу после запуска, то есть работник 2 после завершения заданий 1 и 3 просто ждет, вместо того, чтобы перенять работу 2 у работника 1.
Это ошибка? Или это должно работать так?
Моя версия PHP:
PHP 7.2.14 (cli) (built: Jan 9 2019 22:23:26) ( ZTS MSVC15 (Visual C++ 2017) x64 )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
По какой-то причине мой Docker потерял самообладание теперь, когда я обновил Windows до 1809, поэтому публикация не прошла тестирование. (Так что извините, нет выхода, чтобы дать атм)
Модифицированный существующий код, который я использую в проекте с вашим счетчиком + сон.
$pool = new Pool(2);
foreach ([0,1,2,3] as $count) {
$pool->submit(
new class ($count) extends Threaded
{
private $count;
public function __construct(int $count)
{
$this->count= $count;
}
public function run()
{
if ($this->count== 0) {
sleep(3);
echo $this->count . " is ready\n";
} else {
echo $this->count . " is ready\n";
}
}
}
);
}
while ($pool->collect());
$pool->shutdown();
Я использую анонимный класс (new class ($count) extends Threaded
) как submit()
пары.
На сервере это работает отлично, используя экземпляр Docker с PHP ZTS 7.2.13 на Alpine 3.8
Других решений пока нет …