调度任务与忙等待

时间:2012-06-20 16:29:33

标签: java java-ee scheduled-tasks threadpool

我需要每隔几个小时执行一项任务,我正在寻找最有效的解决方案。我想到了两种方法:

1)忙着等待

while(true){

 doMyJob()
 wait(2*hour);

}

2)执行者安排:

executor.schedule(new MyJobTask(),2,TimeUnit.HOUR);

...

class MyJobTask implements Runnable{

void run(){

 doMyJob();
 ...
 executor.schedule(new MyJobTask(),2,TimeUnit.HOUR);

}

您能告诉我哪种解决方案更有效率,以及在哪种情况下更优选(如果有的话)。直觉上,我会寻求第二种解决方案,但我找不到任何证明我直觉的东西。如果您有其他解决方案 - 请分享。解决方案也应该具有内存效率(这就是我遇到困境的原因 - 我是否需要创建并保留一个ThreadPool对象,每两个小时只执行一次简单的工作)。

2 个答案:

答案 0 :(得分:3)

建议的解决方案中没有一个在EE容器中是真的可取的(你应该避免弄乱线程),你似乎根据问题的标记来定位。

从Java EE 5开始,有timer service根据我的测试可以很好地处理更长的超时时间,比如你的例子中的2小时。有一点,你真的不应该忘记 - 引用上述教程:

  

定时器是持久的。如果服务器关闭(甚至崩溃),则会保存计时器,并在重新启动服务器时再次激活计时器。如果计时器在服务器关闭时到期,则容器将在服务器重新启动时调用@Timeout方法。

如果由于某种原因无法接受此解决方案,您应该查看Quartz Scheduler。到目前为止,它的可能性超出了您的要求,但至少它为您提供了一个随时可用的解决方案,它可以保证与各种应用服务器的兼容性。

答案 1 :(得分:1)

两者应具有相同的效率,但我建议使用ScheduledExecutorService

Executors.newSingleThreadScheduledExecutor()
    .scheduleAtFixedRate(new MyJobTask(), 0, 2, TimeUnit.HOUR);

有几个原因,详见:A better way to run code for a period of time

但重要的是,ScheduledExecutorService允许您使用多个线程,以便花费很长时间的任务不一定需要备份您的任务队列(该服务可以同时运行2个任务) 。此外,如果doMyJob引发异常,ScheduledExecutorService将继续安排您的任务而不是被取消,因为它无法重新安排任务。