Является ли Sleep() хорошей идеей для основного цикла приложения для планирования заданий?

StackOverflow https://stackoverflow.com/questions/1179301

Вопрос

Я пишу приложение для планирования заданий на Ruby для своей работы (в первую очередь для перемещения файлов с использованием различных протоколов с заданной частотой).

Мой основной цикл выглядит так:

while true do
  # some code to launch the proper job
  sleep CONFIG["interval"]
end

Он работает как шарм, но я не совсем уверен, достаточно ли он безопасен, поскольку приложение может работать на сервере с запущенным программным обеспечением, интенсивно использующим процессор.

Есть ли другой способ сделать то же самое или sleep() достаточно безопасно в моем случае?

Это было полезно?

Решение

Использование сна, скорее всего, подойдет для быстрых и грязных дел.Но для вещей, которым требуется немного больше устойчивости или надежности, я полагаю, что сон — это зло :) Проблема со сном заключается в том, что поток (я предполагаю, что Windows здесь...) действительно спит — планировщик не будет запускать поток пока не пройдет некоторое время после интервала сна.

За это время поток ни по чему не проснется.Это означает, что его нельзя отменить или активировать для обработки какого-либо события.Конечно, процесс можно убить, но это не дает спящему потоку возможности проснуться и что-нибудь почистить.

Я не знаком с Ruby, но предполагаю, что у него есть какая-то возможность ожидания выполнения нескольких задач.Если можете, я предлагаю вместо сна подождать двух вещей\

  1. Таймер, который периодически пробуждает поток для выполнения своей работы.
  2. Событие, которое устанавливается, когда процессу необходимо отменить или завершить его (например, перехват Control-C).

Было бы еще лучше, если бы существовало какое-то событие, которое можно было бы использовать для сигнала о необходимости выполнения работы.Это позволит избежать опроса по таймеру.Обычно это приводит к более низкому использованию ресурсов и более быстрому реагированию системы.

Другие советы

Каждый раз, когда я чувствую необходимость заблокировать, я использую цикл обработки событий;обычно либев.Вот привязка Ruby:

http://rev.rubyforge.org/rdoc/

По сути, sleep это совершенно нормально, если вы хотите, чтобы ваш процесс заснул, и в фоновом режиме ничего не происходило.Однако если вы когда-нибудь захотите сделать что-то еще, например, перейти в режим сна, а также дождаться, пока TCP-соединения или дескриптор файла станут доступны для чтения, вам придется использовать цикл событий.Итак, почему бы просто не использовать его вначале?

Поток вашего приложения будет:

main {
   Timer->new( after => 0, every => 60 seconds, run => { <do your work> } )
   loop();
}

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

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

Пока sleep(timeout) идеально подходит для некоторых проектов, следует иметь в виду одно важное предостережение.

Ruby устанавливает обработчики сигналов с помощью SA_RESTART (видеть здесь), что означает, что ваш sleep (или эквивалент select(nil, nil, nil, timeout)) невозможно легко прервать.Ваш обработчик сигнала сработает, но программа вернется обратно к sleep.Это может быть неудобно, если вы хотите своевременно отреагировать, скажем, на SIGTERM.

Считают, что ...

#! /usr/bin/ruby
Signal.trap("USR1") { puts "Hey, wake up!" }
Process.fork() { sleep 2 and Process.kill("USR1", Process.ppid) }
sleep 30
puts "Zzz.  I enjoyed my nap."

...выполнение займет около 30 секунд, а не 2.

В качестве обходного пути вы можете вместо этого создать исключение в обработчике сигнала, которое прервет сон (или что-нибудь еще!), описанное выше.Вы также можете переключиться на select-цикл и использовать вариант трюк с самодельной трубкой проснуться «рано» при получении сигнала.Как отмечали другие, также доступны полнофункциональные библиотеки событий.

Он не будет использовать процессор, пока он спит, но если вы спите долгое время, меня больше беспокоит работающий интерпретатор Ruby, задерживающий память, пока он ничего не делает.Хотя это не так уж и важно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top