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

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

Данный текст является ознакомительным фрагментом.