Программирование на языке Ruby
Программирование на языке Ruby читать книгу онлайн
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
13.2.6. Тайм-аут при выполнении операций
Часто встречается ситуация, когда на выполнение операции отводится определенное максимальное время. Это позволяет избежать бесконечных циклов и более строго контролировать порядок работы. Подобная возможность очень полезна, в частности, в сетевых приложениях, где ответ от сервера может и не прийти.
Библиотека
timeout.rb
timeout
TimeoutError
rescue
require 'timeout.rb'
flag = false
answer = nil
begin
timeout(5) do
puts "Хочу печенье!"
answer = gets.chomp
flag = true
end
rescue TimeoutError
flag = false
end
if flag
if answer == "cookie"
puts "Спасибо! Хрум, хрум..."
else
puts "Это же не печенье!"
exit
end
else
puts "Эй, слишком медленно!"
exit
end
puts "До встречи..."
13.2.7. Ожидание события
Часто один или несколько потоков следят за «внешним миром», а остальные выполняют полезную работу. Все примеры в этом разделе надуманные, но общий принцип они все же иллюстрируют.
В следующем примере прикладную задачу решают три потока. Четвертый поток каждые пять секунд просыпается, проверяет глобальную переменную
$flag
$flag = false
work1 = Thread.new { job1() }
work2 = Thread.new { job2() }
work3 = Thread.new { job3() }
thread4 = Thread.new { Thread.stop; job4() }
thread5 = Thread.new { Thread.stop; job5() }
watcher = Thread.new do
loop do
sleep 5
if $flag
thread4.wakeup
thread5.wakeup
Thread.exit
end
end
end
Если в какой-то момент выполнения метода
job
$flag
true
thread4
thread5
watcher
В следующем примере мы ждем создания файла. Каждые 30 секунд проверяется его существование, и как только файл появится, мы запускаем новый поток. Тем временем остальные потоки занимаются своим делом. На самом деле ниже мы наблюдаем за тремя разными файлами.
def waitfor(filename)
loop do
if File.exist? filename
file_processor = Thread.new { process_file(filename) }
Thread.exit
else
sleep 30
end
end
end
waiter1 = Thread.new { waitfor("Godot") }
sleep 10
waiter2 = Thread.new { waitfor("Guffman") }
sleep 10
headwaiter = Thread.new { waitfor("head") }
# Основной поток занимается другими делами...
Есть много ситуаций, когда поток должен ожидать внешнего события (например, в сетевых приложениях так бывает, когда сервер на другом конце соединения работает медленно или ненадежно).
13.2.8. Продолжение обработки во время ввода/вывода
Часто приложению приходится выполнять одну или более длительных операций ввода/вывода. Прежде всего, речь идет о вводе данных с клавиатуры, поскольку человек печатает куда медленнее, чем вращается диск. Это время можно употребить на пользу с помощью потоков.
Возьмем, к примеру, шахматную программу, которая должна ждать, пока человек сделает ход. Конечно, мы можем изложить только сам принцип, не вдаваясь в технические детали.
Предположим, что итератор
predict_move
scenario = {} # Хэш ход-ответ.
humans_turn = true
thinking_ahead = Thread.new(board) do
predict_move do |m|
scenario[m] = my_response(board,m)
Thread.exit if humans_turn == false
end
end
human_move = get_human_move(board)