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
при возникновении исключения завершается безусловно).
t1 = Thread.new do
puts 'Привет!'
sleep 2
raise 'some exception'
puts 'Пока!'
end
t2 = Thread.new { sleep 100 }
sleep 2
puts 'Конец'
# Выводится:
Привет!
Конец
13.1.6. Группы потоков
Default
(это константа класса). Но если создать новую группу, то в нее можно будет помещать потоки.
В любой момент времени поток может принадлежать только одной группе. Если поток помещается в группу, то он автоматически удаляется из той группы, которой принадлежал ранее.
Метод класса ThreadGroup.new
создает новую группу потоков, а метод экземпляра add
помещает поток в группу.
f1 = Thread.new('file1') { |file| waitfor(file) }
f2 = Thread.new('file2') { |file| waitfor(file) }
file_threads = ThreadGroup.new
file_threads.add f1
file_threads.add f2
Метод экземпляра list
возвращает массив всех потоков, принадлежащих данной группе.
# Подсчитать все 'живые' потоки в группе this_group.
count = 0
this_group.list.each {|x| count += 1 if x.alive? }
if count < this_group.list.size
puts 'Некоторые потоки в группе this_group уже скончались.'
else
puts 'Все потоки в группе this_group живы.'
end
В класс ThreadGroup
можно добавить немало полезных методов. В примере ниже показаны методы для возобновления всех потоков, принадлежащих группе, для группового ожидания потоков (с помощью join
) и для группового завершения потоков:
class ThreadGroup
def wakeup
list.each { |t| t.wakeup }