Java定时器与ExecutorService?
我有我使用java.util.timer
计划任务的代码。 我环顾四周,看到ExecutorService
可以做同样的事情。 所以这里的这个问题,你使用Timer和ExecutorService
来调度任务,一个使用另一个的好处是什么?
也想检查是否有人使用了Timer
类,并遇到ExecutorService
为他们解决的任何问题。
根据Java并发实践 :
-
Timer
可以对系统时钟的变化敏感,ScheduledThreadPoolExecutor
不是。 -
Timer
只有一个执行线程,所以长时间运行的任务可以延迟其他任务。ScheduledThreadPoolExecutor
可以configuration任意数量的线程。 此外,你可以完全控制创build的线程,如果你想(通过提供ThreadFactory
)。 -
TimerTask
抛出的运行时exceptionTimerTask
一个线程,从而导致Timer
死机:-( …即计划的任务将不再运行afterExecute
不仅捕获运行时exception,但它可以让你处理它们,如果你想(通过重写afterExecute
方法ThreadPoolExecutor
)抛出exception的任务将被取消,但其他任务将继续运行。
如果您可以使用ScheduledThreadExecutor
而不是Timer
,那就这样做。
还有一件事情…虽然ScheduledThreadExecutor
在Java 1.4库中不可用,但是Java 1.2,1.3,1.4的JSR 166( java.util.concurrent
)的Backport具有ScheduledThreadExecutor
类。
如果它对您有用,那么很难想到不使用Java 5执行器框架的原因。 呼叫:
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
会给你一个与Timer
类似的ScheduledExecutorService
(即它将是单线程的),但是它的访问可能稍微更具可扩展性(在引擎盖下,它使用并发结构而不像Timer
类那样完成同步)。 使用ScheduledExecutorService
还可以带来以下优点:
- 您可以根据需要自定义它(请参阅
newScheduledThreadPoolExecutor()
或ScheduledThreadPoolExecutor
类) - “一次性”执行可以返回结果
坚持Timer
我可以想到的唯一原因是:
- 它在Java 5之前是可用的
- 在J2ME中提供了一个类似的类,它可以使你的应用程序更容易移植(但是在这种情况下增加一个通用的抽象层并不是件难事)
ExecutorService更新更通用。 计时器只是一个定期运行你已经安排好的东西的线程。
一个ExecutorService可能是一个线程池,甚至跨群集中的其他系统分布,并执行一次性批处理执行等等。
只要看看每个提供的决定。
以下是围绕Timer使用的一些更好的实践:
http://tech.puredanger.com/2008/09/22/timer-rules/
一般来说,我会使用计时器快速和肮脏的东西和执行器更强大的用法。
我有时宁愿使用Timer over Executors.newSingleThreadScheduledExecutor()的理由是,当我需要定时器在守护进程线程上执行时,我得到了更清晰的代码。
比较
private final ThreadFactory threadFactory = new ThreadFactory() { public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setDaemon(true); return t; } }; private final ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(threadFactory);
同
private final Timer timer = new Timer(true);
当我不需要executorservice的鲁棒性,我这样做。
从ScheduledThreadPoolExecutor的 oralce文档页面
一个ThreadPoolExecutor ,它可以附加地计划命令在给定延迟之后运行,或者定期执行。 当需要多个工作线程时,或者需要额外的灵活性或ThreadPoolExecutor(该类扩展)的function时,此类比Timer更可取。
有多个工作线程时, ExecutorService/ThreadPoolExecutor
或ScheduledThreadPoolExecutor
是显而易见的select。
ExecutorService
优于Timer
优点
-
Timer
不能像ExecutorService
那样利用可用的CPU内核,特别是使用ExecutorService
多个任务,比如ForkJoinPool - 如果您需要多任务之间的协调,则
ExecutorService
提供协作API。 假设你必须提交N个工作任务并等待所有工作完成。 你可以用invokeAll API轻松实现。 如果你想在多个Timer
任务中实现同样的function,那将不是那么简单。 -
ThreadPoolExecutor为线程生命周期的pipe理提供了更好的API。
线程池解决了两个不同的问题:由于减less了每个任务的调用开销,它们通常在执行大量的asynchronous任务时提供改进的性能,并且提供了一种限制和pipe理资源(包括线程)的方法,在执行任务。 每个ThreadPoolExecutor还维护一些基本的统计信息,例如完成的任务数量
几个优点:
一个。 您可以创build/pipe理/控制线程的生命周期并优化线程创build成本的开销
湾 您可以控制任务的处理(工作偷窃,ForkJoinPool,invokeAll)等
C。 您可以监视线程的进度和健康状况
d。 提供更好的exception处理机制