Вход/Регистрация
Программирование на языке Ruby
вернуться

Фултон Хэл

Шрифт:

# Ничего не делать...

 end

end

sleep 0.01 # На вашей машине значение может быть иным.

if factorial1000.alive?

 factorial1000.raise("Стоп!")

 puts "Вычисление было прервано!"

else

 puts "Вычисление успешно завершено."

end

Поток, запущенный в предыдущем примере, пытался вычислить факториал 1000. Если для этого не хватило одной сотой секунды, то главный поток завершит его. Как следствие, на относительно медленной машине будет напечатано сообщение «Вычисление было прервано!» Что касается части

rescue
внутри потока, то в ней мог бы находиться любой код, как, впрочем, и всегда.

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

13.1.5. Обработка исключений

Что произойдет, если в потоке возникнет исключение? Как выясняется, поведение можно сконфигурировать заранее.

Существует флаг

abort_on_exception
, который работает как на уровне класса, так и на уровне экземпляра. Он реализован в виде метода доступа (то есть позволяет читать и устанавливать атрибут) на обоих уровнях. Если
abort_on_exception
для некоторого потока равен
true
, то при возникновении в этом потоке исключения будут завершены и все остальные потоки.

Thread.abort_on_exception = true

t1 = Thread.new do

 puts "Привет!"

 sleep 2

 raise "some exception"

 puts "Пока!"

end

t2 = Thread.new { sleep 100 }

sleep 2

puts "Конец"

В этом примере флаг

abort_on_exception
установлен в
true
на уровне системы в целом (отменяя подразумеваемое по умолчанию значение). Следовательно, когда в потоке
t1
возникает исключение, завершаются и
t1
, и главный поток. Печатается только слово «Привет!».

В следующем примере эффект такой же:

t1 = Thread.new do

 puts "Привет!"

 sleep 2

 raise "some exception"

 puts "Пока!"

end

t1.abort_on_exception = true

t2 = Thread.new { sleep 100 }

sleep 2

puts "Конец"

А вот в следующем оставлено принимаемое по умолчанию значение

false
, и мы наконец-то видим слово «Конец», печатаемое главным потоком (слова «Пока!» мы не увидим никогда, поскольку поток
t1
при возникновении исключения завершается безусловно).

  • Читать дальше
  • 1
  • ...
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: