【问题标题】:Scheduling task vs busy waiting调度任务 vs 忙等待
【发布时间】:2012-06-22 20:26:38
【问题描述】:

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

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 对象只是为了每两个小时做一个简单的工作)。

【问题讨论】:

标签: java jakarta-ee scheduled-tasks threadpool


【解决方案1】:

在 EE 容器中建议的解决方案都不是真正可取的(您应该避免与线程混淆),您似乎根据问题的标签来定位它。

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

定时器是持久的。如果服务器关闭(甚至崩溃),计时器会被保存,并在服务器重新启动时再次变为活动状态。如果服务器宕机时定时器超时,容器会在服务器重启时调用@Timeout方法。

如果由于某种原因该解决方案不可接受,您应该查看Quartz Scheduler。它的可能性远远超出了您的要求,但至少它为您提供了一个即用型解决方案,保证了与各种应用服务器的兼容性。

【讨论】:

    【解决方案2】:

    两者的效率应该差不多,但我建议使用ScheduledExecutorService

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

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

    但重要的是,ScheduledExecutorService 允许您使用多个线程,这样需要很长时间的任务就不必备份您的任务队列(该服务可以同时运行您的两个任务)。此外,如果doMyJob 抛出异常,ScheduledExecutorService 将继续安排您的任务,而不是因为未能重新安排任务而被取消。

    【讨论】:

    • 这真的不像我会在 EJB 中做的事情。您认为这不会造成问题,因此您更喜欢 EJB 计时器服务?
    猜你喜欢
    • 1970-01-01
    • 2019-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-04
    • 1970-01-01
    • 1970-01-01
    • 2015-03-13
    相关资源
    最近更新 更多