Курс языка программирования Raku / Функциональное, конкурентное, реактивное и веб-программирование / Конкурентное программирование / Потоки

Присоединение потоков

Чтобы дождаться завершения потока, вызовите у него .finish (то же самое пишется и как .join). Основная программа приостанавливается на этом месте, пока поток не закончит:

my $t = Thread.start({ say 'in the thread' });
$t.finish;
say 'done';

Программа печатает:

in the thread
done

Поскольку .finish ждёт, сообщение потока гарантированно появится раньше done. Без .finish порядок был бы непредсказуем, а программа могла бы даже завершиться прежде, чем поток успел бы что-то напечатать.

Когда вы запускаете несколько потоков, каждый из них присоединяют, чтобы убедиться, что все они завершились:

my $a = Thread.start({ 1 + 1 });
my $b = Thread.start({ 2 + 2 });
$a.finish;
$b.finish;
say 'both finished';

Два потока выполняются одновременно, и присоединение обоих до последнего say гарантирует, что both finished напечатается только после того, как они действительно закончат. Присоединение — это способ свести конкурентную работу обратно к предсказуемой точке в вашей программе.

Поскольку вызов метода у джанкшена распространяется на каждое хранимое им значение, несколько потоков можно присоединить одним выражением. Объедините их оператором all& — и вызовите .finish у джанкшена:

my $a = Thread.start({ 1 + 1 });
my $b = Thread.start({ 2 + 2 });

($a & $b).finish;
say 'both finished';

Вызов .finish у $a & $b выполняет его для обоих потоков, поэтому программа ждёт, пока не останется ни одного работающего, — тот же результат, что и при поочерёдном присоединении, но читается это как «заверши оба» и работает для любого числа потоков, объединённых через &.

Навигация по курсу

Тест — Потоки   |   Выполните в потоке


💪 Или перейдите сразу к упражнениям этого раздела.