我正在为我的工作用 Ruby 编写一个作业调度应用程序(主要是按照给定频率使用各种协议移动文件)

我的主循环如下所示:

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

它的工作方式就像一个魅力,但我不确定它是否足够安全,因为该应用程序可能运行在运行 CPU 密集型软件的服务器上。

有没有另一种方法可以做同样的事情,或者是 sleep() 就我而言足够安全吗?

有帮助吗?

解决方案

对于快速而肮脏的事情,使用睡眠可能是可以的。但对于需要更多鲁棒性或可靠性的事情,我建议睡眠是邪恶的:)睡眠的问题是线程(我假设 Windows 这里......)真正睡着了 - 调度程序不会运行线程直到睡眠间隔过去一段时间。

在此期间,线程不会因为任何事情而被唤醒。这意味着它无法被取消,或唤醒以处理某种事件。当然,该进程可以被终止,但这并不会给休眠线程一个唤醒并清理任何东西的机会。

我对 Ruby 不熟悉,但我认为它有某种功能可以等待多种事情。如果可以的话,我建议您不要使用睡眠,而是等待两件事\

  1. 定期唤醒线程以完成其工作的计时器。
  2. 当进程需要取消或停止时设置的事件(例如捕获 control-C)。

如果有某种事件可以用来表示需要工作,那就更好了。这将避免轮询计时器。这通常会导致资源利用率降低和系统响应速度更快。

其他提示

任我觉得有必要阻止,我使用的事件循环;通常libev。这里是一个Ruby结合:

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

基本上,如果你希望你的过程中去,而无需其他任何东西在后台会在睡觉sleep是完全没有问题。如果你想要做其他的事情,不过,喜欢睡觉,也等待TCP连接或文件句柄成为可读,那么你将不得不使用事件循环。那么,为什么不直接使用一个开头?

应用程序的流程是:

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

当你想要做其他的东西,你只需要创建守望,和它发生了你。 (所运行的作业也可以创建观察者。)

如果你并不需要一个精确的时间间隔,那么对我来说很有意义。如果您需要以固定的时间被唤醒而不随波逐流,你可能想使用某种形式的外部计时器。但是,当你睡着了,你不使用CPU资源。它的任务切换这是昂贵的。

虽然sleep(timeout)是完全适合一些设计,还有要记住一个重要的警告。

红宝石安装信号处理程序与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环和使用自管招的变体醒“早”在接收到的信号。正如其他人所指出的,全功能的事件库可用了。

它不会使用CPU,而它在睡觉,但如果你睡了很长一段时间我会更关注运行Ruby解释拿着内存,而它没有做任何事情的。这不是什么大不了的事寿。

scroll top