Программирование на языке Ruby.

13.1.4. Назначение рандеву (и получение возвращенного значения).

Иногда главный поток хочет дождаться завершения другого потока. Для этой цели предназначен метод join:

T1 = Thread.new { do_something_long() }.

Do_something_brief().

T1.join # Ждать завершения t1.

Отметим, что вызывать метод join необходимо, если нужно дождаться завершения другого потока. В противном случае главный поток завершится, а вместе с ним и все остальные. Например, следующий код никогда не напечатал бы окончательный ответ, не будь в конце вызова join:

Meaning_of_life = Thread.new do.

 puts "Смысл жизни заключается в...".

 sleep 10.

 puts 42.

End.

Sleep 9.

Meaning_of_life.join.

Существует полезная идиома, позволяющая вызвать метод join для всех «живых» потоков, кроме главного (ни один поток, даже главный, не может вызывать join для самого себя).

Thread.list.each { |t| t.join if t != Thread.main }.

Конечно, любой поток, а не только главный, может вызвать join для любого другого потока. Если главный поток и какой-то другой попытаются вызвать join друг для друга, возникнет тупиковая ситуация. Интерпретатор обнаружит это и завершит программу.

Thr = Thread.new { sleep 1; Thread.main.join }.

Thr.join # Тупиковая ситуация!

С потоком связан блок, который может возвращать значение. Следовательно, и сам поток может возвращать значение. Метод value неявно вызывает join и ждет, пока указанный поток завершится, а потом возвращает значение последнего вычисленного в потоке выражения.

Max = 10000.

Thr = Thread.new do.

 sum = 0.

 1.upto(max) { |i| sum += i }.

 sum.

End.

Guess = (max*(max+1))/2.

Print "Формула ".

If guess == thr.value.

 puts "правильна.".

Else.

 puts "неправильна.".

End.