Вчера мы видели, как создаются параллельные потоки с помощью слова start. Сегодня мы чуть подробнее остановимся на этом.
Вызов start создает промис, который выполняет блок кода параллельно основному потоку. После создания промиса управление тут же передается в основную программу, поэтому необходимо дождаться завершения работы треда.
my $promise = start {
sleep 2;
say 'Done';
}
say 'Waiting...';
await $promise;
Эта программа создает промис $promise и ждет его выполнения. На печати появляется следующее:
$ perl6 start-1.pl Waiting... Done
Если убрать строку с await, то программа завершится прежде чем завершит работу блок кода из промиса, поэтому Done напечатано не будет.
Разумеется, возможно создать более одного промиса, и все они будут выполняться параллельно.
my @promises;
for 1..10 -> $n {
push @promises, start {
say "Done $n";
}
}
say 'Waiting...';
await @promises;
Теперь создано десять потоков, и все они начинают работать сразу после создания. Поскольку на этот раз блок кода не содержит sleep, вывод программы может отличаться от запуска к запуску, например:
$ perl6 start-2.pl Done 1 Done 2 Done 3 Done 4 Done 5 Done 6 Waiting... Done 7 Done 8 Done 9 Done 10
Вместо того, чтобы сохранять промисы в массиве (это нужно, чтобы было что передать await), удобно воспользоваться вот таким приемом с gather и take:
await gather for 1..10 -> $n {
take start {
say "Done $n";
}
}
say 'Waiting...';
Еще проще конструкция с do:
await do for 1..10 -> $n {
start {
say "Done $n";
}
}
say 'Waiting...';
Синтаксически, слово start — это префиксный оператор, который делает то же самое что и вызов одноименного метода класса Promise. Первую программу можно было бы переписать так:
my $promise = Promise.start({
sleep 2;
say 'Done';
});
say 'Waiting...';
await $promise;
Перед тем, как попрощаться сегодня, маленькое замечание: метод start применяется еще в нескольких ситуациях: при создании тредов, сапплаев и при запуске внешнего процесса. Поговорим обо всем этом в следующий раз.
Вначале все было просто и понятно, но на втором абзаце gather take я сломался. )
А в порядке создания/вызовы результаты возможно получить?
Как-то так, например: for 1..10 -> $n { start {@a[$n] = «Done $n» } }