Чтение онлайн

на главную - закладки

Жанры

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

 puts "beta"

end

t2 = Thread.new do

 puts "gamma"

 puts "delta"

end

t1.join

t2.join

В этом искусственном примере вызов

Thread.pass
приводит к печати строк в следующем порядке:
alpha gamma delta beta
. Без него было бы напечатано
alpha beta gamma delta
. Конечно, этот механизм следует использовать не для синхронизации, а только для экономного расходования процессорного времени.

Выполнение приостановленного потока можно возобновить методами методами

run
или
wakeup
:

t1 = Thread.new do

 Thread.stop

 puts "Здесь есть изумруд."

end

t2 = Thread.new do

 Thread.stop

 puts "Вы находитесь в точке Y2."

end

sleep 1

t1.wakeup

t2.run

Между этими методами есть тонкое различие. Метод

wakeup
изменяет состояние потока, так что он становится готовым к выполнению, но не запускает его немедленно. Метод же
run
пробуждает поток и сразу же планирует его выполнение.

В данном случае

t1
просыпается раньше
t2
, но
t2
планируется первым, что приводит к следующему результату:

Вы находитесь в точке Y2.

Здесь есть изумруд.

Конечно, было бы неосмотрительно реализовывать синхронизацию на основе этого механизма.

Метод экземпляра

raise
возбуждает исключение в потоке, от имени которого вызван. (Этот метод необязательно вызывать в том потоке, которому адресовано исключение.)

factorial1000 = Thread.new do

 begin

prod = 1

1.upto(1000) {|n| prod *= n }

puts "1000! = #{prod}"

 rescue

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

 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
, то при возникновении в этом потоке исключения будут завершены и все остальные потоки.

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

Личный аптекарь императора. Том 5

Карелин Сергей Витальевич
5. Личный аптекарь императора
Фантастика:
городское фэнтези
попаданцы
аниме
сказочная фантастика
фэнтези
7.50
рейтинг книги
Личный аптекарь императора. Том 5

Глэрд IX: Легионы во Тьме

Владимиров Денис
9. Глэрд
Фантастика:
боевая фантастика
попаданцы
фэнтези
5.00
рейтинг книги
Глэрд IX: Легионы во Тьме

Ученик

Листратов Валерий
2. Ушедший Род
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Ученик

Звездная Кровь. Экзарх I

Рокотов Алексей
1. Экзарх
Фантастика:
боевая фантастика
рпг
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Звездная Кровь. Экзарх I

Тринадцатый XII

NikL
12. Видящий смерть
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
7.00
рейтинг книги
Тринадцатый XII

Хозяин Теней 5

Петров Максим Николаевич
5. Безбожник
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Хозяин Теней 5

#НенавистьЛюбовь

Джейн Анна
Любовные романы:
современные любовные романы
6.33
рейтинг книги
#НенавистьЛюбовь

Бастард Императора. Том 2

Орлов Андрей Юрьевич
2. Бастард Императора
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Бастард Императора. Том 2

Я царь. Книга XXVIII

Дрейк Сириус
28. Дорогой барон!
Фантастика:
боевая фантастика
аниме
попаданцы
5.00
рейтинг книги
Я царь. Книга XXVIII

Эпоха Опустошителя. Том V

Павлов Вел
5. Вечное Ристалище
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Эпоха Опустошителя. Том V

Сильнейший ученик. Том 2

Ткачев Андрей Юрьевич
2. Пробуждение крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сильнейший ученик. Том 2

Цикл "Отмороженный". Компиляция. Книги 1-14

Гарцевич Евгений Александрович
Отмороженный
Фантастика:
боевая фантастика
рпг
постапокалипсис
5.00
рейтинг книги
Цикл Отмороженный. Компиляция. Книги 1-14

Мастер 2

Чащин Валерий
2. Мастер
Фантастика:
фэнтези
городское фэнтези
попаданцы
технофэнтези
4.50
рейтинг книги
Мастер 2

Вернувшийся: Новая жизнь. Том I

Vector
1. Вернувшийся
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Вернувшийся: Новая жизнь. Том I