13.1.3. Опрос и изменение состояния потока
13.1.3. Опрос и изменение состояния потока
В классе Thread есть несколько полезных методов класса. Метод list возвращает массив «живых» потоков, метод main возвращает ссылку на главный поток программы, который породил все остальные, а метод current позволяет потоку идентифицировать самого себя.
t1 = Thread.new { sleep 100 }
t2 = Thread.new do
if Thread.current == Thread.main
puts "Это главный поток." # HE печатается,
end
1.upto(1000) { sleep 0.1 }
end
count = Thread.list.size # 3
if Thread.list.include ?(Thread.main)
puts "Главный поток жив." # Печатается всегда!
end
if Thread.current == Thread.main
puts "Я главный поток." # Здесь печатается...
end
Методы exit, pass, start, stop и kill служат для управления выполнением потоков (как изнутри, так и извне):
# в главном потоке...
Thread.kill(t1) # Завершить этот поток.
Thread.pass # Передать управление t2.
t3 = Thread.new do
sleep 20
Thread.exit # Выйти из потока.
puts "Так не бывает!" # Никогда не выполняется.
end
Thread.kill(t2) # Завершить t2.
# Выйти из главного потока (все остальные тоже завершаются).
Thread.exit
Отметим, что не существует метода экземпляра stop, поэтому поток может приостановить собственное выполнение, но не выполнение другого потока.
Существуют различные методы для опроса состояния потока. Метод экземпляра alive? сообщает, является ли данный поток «живым» (не завершил выполнение), а метод stop? — находится ли он в состоянии «приостановлен».
count = 0
t1 = Thread.new { loop { count += 1 } }
t2 = Thread.new { Thread.stop }
sleep 1
flags = [t1.alive?, # true
t1.stop?, # false
t2.alive?, # true
t2.stop?] # true
Получить состояние потока позволяет метод status. Он возвращает значение "run", если поток выполняется; "sleep" — если он приостановлен, спит или ожидает результата ввода/вывода; false — если поток нормально завершился, и nil — если поток завершился в результате исключения.
t1 = Thread.new { loop {} }
t2 = Thread.new { sleep 5 }
t3 = Thread.new { Thread.stop }
t4 = Thread.new { Thread.exit }
t5 = Thread.new { raise "exception" }
s1 = t1.status # "run"
s2 = t2.status # "sleep"
s3 = t3.status # "sleep"
s4 = t4.status # false
s5 = t5.status # nil
Глобальную переменную $SAFE можно установить по-разному в разных потоках. Стало быть, она вовсе не является глобальной, но стоит ли жаловаться на это, если она позволяет разным потокам работать с разным уровнем безопасности? Метод safe_level возвращает текущий уровень безопасности потока.
t1 = Thread.new { $SAFE = 1; sleep 5 }
t2 = Thread.new { $SAFE = 3; sleep 5 }
sleep 1
lev0 = Thread.main.safe_level # 0
lev1 = t1.safe_level # 1
lev2 = t2.safe_level # 3
Метод доступа priority позволяет узнать и изменить приоритет потока:
t1 = Thread.new { loop { sleep 1 } }
t2 = Thread.new { loop { sleep 1 } }
t2.priority = 3 # Установить для потока t2 приоритет 3
p1 = t1.priority # 0
p2 = t2.priority # 3
Поток с большим приоритетом будет чаще получать процессорное время. Специальный метод pass позволяет передать управление планировщику. Иными словами, поток просто уступает свой временной квант, но не приостанавливается и не засыпает.
t1 = Thread.new do
puts "alpha"
Thread.pass
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 внутри потока, то в ней мог бы находиться любой код, как, впрочем, и всегда.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
Изменение состояния виртуальной машины
Изменение состояния виртуальной машины В отличие от продуктов, рассмотренных в двух предыдущих главах, Parallels Workstation предоставляет минимальный набор средств для управления текущим состоянием виртуальной машины после ее запуска.Доступных вариантов всего три: выключение,
Опрос состояния службы
Опрос состояния службы Для получения структурой SERVICE_STATUS текущего состояния службы используется следующая функция: BOOL QueryServiceStatus(SC_HANDLE hService, LPSERVICE_STATUS
Опрос и установка часов реального времени, и кое-что еще
Опрос и установка часов реального времени, и кое-что еще Независимо от применения таймеров, вы можете также опрашивать и устанавливать часы реального времени, а также и плавно подстраивать их. Для этих целей можно использовать следующие
Данные потока
Данные потока В реальном коде часто возникает ситуация, когда одновременно исполняются несколько экземпляров потоков, использующих один и тот же код (при создании потоков указывается одна и та же функция потока). При этом некоторые данные (например, статические объекты,
Завершение потока
Завершение потока Как и в случае обсуждавшегося ранее завершения процесса, для потоков мы будем отчетливо различать случаи:• «естественного» завершения выполнения потока из кода самого потока;• завершения потока извне, из кода другого потока или по сигналу. Для этого
Приложение 2 МЕЖДУНАРОДНЫЙ ОПРОС 2003 ГОДА ПО ИНФОРМАЦИОННОЙ БЕЗОПАСНОСТИ. ОБЗОР РЕЗУЛЬТАТОВ ПО СТРАНАМ СНГ
Приложение 2 МЕЖДУНАРОДНЫЙ ОПРОС 2003 ГОДА ПО ИНФОРМАЦИОННОЙ БЕЗОПАСНОСТИ. ОБЗОР РЕЗУЛЬТАТОВ ПО СТРАНАМ СНГ В начале 2004 года компания «Эрнст энд Янг» опубликовала результаты своего исследования состояния информационной безопасности в СНГ ( www.eu.com/russia ). В этом исследовании
14.9. Расширенный опрос
14.9. Расширенный опрос В начале этой главы мы рассказывали о способах установки таймеров для операций с сокетами. Во многих операционных системах для этого существуют функции poll и select, которые были описаны в главе 6. Ни один из этих методов еще не стандартизован POSIX, поэтому
10.3.4 Опрос терминала
10.3.4 Опрос терминала Иногда удобно производить опрос устройства, то есть считывать с него данные, если они есть, или продолжать выполнять обычную работу — в противном случае. Программа на Рисунке 10.18 иллюстрирует этот случай: после открытия терминала с параметром "no delay"
10.1.12. Опрос специальных свойств файла
10.1.12. Опрос специальных свойств файла У файла есть много свойств, которые можно опросить. Мы перечислим в этом разделе те встроенные методы, для которых не нашлось другого места. Почти все они являются предикатами.Читая этот раздел (да и большую часть этой главы), помните о
11.1.6. Опрос класса объекта
11.1.6. Опрос класса объекта Часто возникает вопрос: «Что это за объект? Как он соотносится с данным классом?» Есть много способов получить тот или иной ответ.Во-первых, метод экземпляра class всегда возвращает класс объекта. Применявшийся ранее синоним type объявлен устаревшим.s
Изменение данных состояния приложения
Изменение данных состояния приложения В ходе выполнения Web-приложения с помощью членов типа HttpApplicationState вы можете программно модифицировать или удалить любые или даже все члены уровня приложения. Например, чтобы удалить конкретный элемент, нужно просто вызвать метод
20.7. Состояния потока
20.7. Состояния потока Пользователей библиотеки iostream, разумеется, интересует, находится ли поток в ошибочном состоянии. Например, если мы пишемint ival;cin ival;и вводим слово "Borges", то cin переводится в состояние ошибки после неудачной попытки присвоить строковый литерал целому
8.4.2 Состояния Потока
8.4.2 Состояния Потока Каждый поток (istream или ostream) имеет ассоциированное с ним состояние, и обработка ошибок и нестандартных условий осуществляется с помощью соответствующей установки и проверки этого состояния.Поток может находиться в одном из следующих состояний:enum
5.3 Мониторинг состояния системы, устранение ошибок, восстановление утерянных файлов и защита данных Анализ состояния аппаратной части системы
Введение Как и всякая техника, персональный компьютер нуждается в техническом обслуживании, настройке и наладке. Небрежное отношение к своей машине приводит к тому, что работа компьютера становится нестабильной и не эффективной. А потом происходит сбой, и компьютер