Как стать автором
Обновить

Ruby знакомство с Thread

Время на прочтение3 мин
Количество просмотров1.1K

Лирическое отступление


Например, мы пишем сервер. Воплощение сервера это зацикливание, постоянный опрос чего-либо. Все мелкодискретное принято считать постоянным, вот и получается постоянное соединение.

Реалии


В руби есть бесконечный цикл loop.
Copy Source | Copy HTML
  1. loop{
  2.   puts "Ничто меня не остановит."
  3. }
  4. #Собственно отсюда и начинаются проблемы.
  5. puts "дело в том, что этот код никогда не выполнится."

Т.е. надо все выполнить до того как мы начали зацикливание.
Кроме того данная операция весьма чувствительна для процессора. Если нам не нужно очень частого повторения, то цикл можно на время и усыплять.
Copy Source | Copy HTML
  1. loop{
  2.   puts "Ничто меня не остановит."
  3.   sleep(1) #одна секунда сна
  4. }

И если нужно выполнять операции с разной частотой, то в рамках одного цикла это проблематично.

Thread


Для решения этих проблем существую потоки.
Типичный поток
Copy Source | Copy HTML
  1. Thread.new{
  2.   loop{
  3.     puts "я тред"
  4.   }
  5. }

Первый опыт


Сейчас я покажу, как я начал исследовать Thread и что для меня стало неожиданностью.
Первая программа с тредами выглядела так, как я написал выше. Когда я ее запустил, ничего не произошло. Первая мысль, которая пришла в голову (причем ошибочная), это, что поток нужно запустить, и я полез в доку в поисках «пускового» метода.
Получилось с помощью join
Не вчитываясь в описание, я решил, что так и запускаются потоки. Далее, для собственного увеселение, я сделал часики:
Copy Source | Copy HTML
  1. thr_1=Thread.new{
  2.   loop{
  3.     sleep(5)
  4.     puts "                Пять"
  5.   }
  6. }
  7. thr_2=Thread.new{
  8.   loop{
  9.     sleep(10)
  10.     puts "ДЕСЯТЬ"
  11.   }
  12. }
  13. thr_3=Thread.new{
  14.   loop{
  15.     sleep(1)
  16.     puts "                                тик"
  17.   }
  18. }

Т.е. программа, в которой операции в циклах выполняются с разной частотой (то о чем писал выше), и буквально случайно обнаружил, что thr_1.join (к примеру) «запускает» все треды, а не только себя.
А дальше было еще страннее, когда я начал пробовать писать в потоках не вечные циклы, а методы. Они могли выполниться, выполниться частично, или вовсе не выполниться. Тучи сгущались, однако сквозь горку тестовых программок я добрался до истины, и вот она какова:

join это не пуск!


Как только мы запускаем свое приложение, то попадаем в Thread.main
Если все операции в нем заканчиваются, то приложение закрывается. Если при этом существуют другие потоки, приложение закрывается, не взирая на них.
Например, если кроме создания тредов больше вообще ничего не делать, то программа завершиться сразу, не выполняя, кода в созданных тредах — то, что происходило со мной в начале.
join делает тред, из которого он вызван спящим, до завершения треда которому он вызван.
Т.е. в начале, я сделал спящим Thread.main до завершения thr_1. Thread.main стал неактивным, но не завершился, ожидая завершение треда thr_1, поэтому приложение так же не завершилось, и другие треды радостно продолжали работать.

Запускаем треды командой спать!


Самый простой способ продлить работу Thread.main — это усыпить его.
Copy Source | Copy HTML
  1. Thread.new{
  2.   puts "Наконец-то"
  3. }
  4. Thread.new{
  5.   puts "мы выполнимся!"
  6. }
  7. sleep 5 # усыпить на время
  8. sleep # или навечно

run


Спящие потоки, в т.ч. Thread.main, можно вновь запустить методом run
А остановить методами sleep или Thread.stop
Copy Source | Copy HTML
  1. thr=Thread.new{
  2.   sleep #z z Z
  3.   puts "..не сплю.."
  4.   puts "и ты не спи"
  5.   Thread.main.run
  6. }
  7. Thread.new{
  8.   sleep 1
  9.   puts "Проснись!"
  10.   thr.run
  11. }
  12. Thread.stop


Все на сегодня с тредами. Это моя первая статья (вообще). Послушаю отзывы и, возможно, продолжу рассказ:)
Теги:
Хабы:
+3
Комментарии26

Публикации

Изменить настройки темы

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн