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

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

Оглавление книги


Генерация: 1.104. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз