Java Timer 与 ExecutorService?
-
03-07-2019 - |
题
我有代码,我使用它来安排任务 java.util.timer
. 。我环顾四周,看到 ExecutorService
可以做同样的事情。那么这个问题,你使用过Timer和 ExecutorService
要安排任务,使用一种方法比另一种方法有什么好处?
还想检查是否有人使用过 Timer
课堂上遇到的任何问题 ExecutorService
为他们解决了。
解决方案
根据 Java 并发实践:
Timer
可以对系统时钟的变化敏感,ScheduledThreadPoolExecutor
不是。Timer
只有一个执行线程,因此长时间运行的任务可能会延迟其他任务。ScheduledThreadPoolExecutor
可以配置任意数量的线程。此外,如果您愿意,您可以完全控制创建的线程(通过提供ThreadFactory
).- 运行时抛出异常
TimerTask
杀死那个线程,从而使Timer
死的 :-( ...IE。计划任务将不再运行。ScheduledThreadExecutor
不仅捕获运行时异常,而且还可以让您根据需要处理它们(通过覆盖afterExecute
方法来自ThreadPoolExecutor
)。抛出异常的任务将被取消,但其他任务将继续运行。
如果你可以使用 ScheduledThreadExecutor
代替 Timer
, , 这样做。
还有一件事...尽管 ScheduledThreadExecutor
在 Java 1.4 库中不可用,有一个 JSR 166 的向后移植(java.util.concurrent
) 到 Java 1.2、1.3、1.4, ,其中有 ScheduledThreadExecutor
班级。
其他提示
如果它对你来说是可用的,那么很难想出理由 不是 使用 Java 5 执行器框架。呼叫:
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
会给你一个 ScheduledExecutorService
具有类似的功能 Timer
(IE。它将是单线程的),但其访问可能稍微更具可扩展性(在幕后,它使用并发结构而不是像 Timer
班级)。用一个 ScheduledExecutorService
还为您带来以下优势:
- 如果需要,您可以自定义它(请参阅
newScheduledThreadPoolExecutor()
或者ScheduledThreadPoolExecutor
班级) - “一次性”执行可以返回结果
关于坚持的唯一理由 Timer
我能想到的有:
- Java 5 之前可用
- J2ME 中提供了类似的类,这可以使应用程序的移植变得更容易(但在这种情况下添加公共抽象层并不是非常困难)
ExecutorService更新,更通用。计时器只是一个定期运行您为其安排的东西的线程。
ExecutorService可以是一个线程池,甚至可以分布在集群中的其他系统上,并执行一次性批处理执行等操作......
看看每个提供的决定。
以下是关于Timer使用的一些更好的做法:
http://tech.puredanger.com/2008/09/22 /定时器的规则/
一般来说,我会使用Timer来快速和脏的东西和Executor使用更强大。
我有时更喜欢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);
当我不需要执行器服务的健壮性时,我这样做。
来自 ScheduledThreadPoolExecutor <上的Oracle文档页面/ A>
当您有多个工作线程时,ThreadPoolExecutor ,可以额外安排命令在给定延迟后运行,或定期执行。当需要多个工作线程时,或者当需要ThreadPoolExecutor(此类扩展)的额外灵活性或功能时,此类优于 Timer 。
ExecutorService / ThreadPoolExecutor
或 ScheduledThreadPoolExecutor
是显而易见的选择。
ExecutorService
优先于 Timer
-
计时器
不能利用可用的CPU核心,这与ExecutorService
不同,特别是使用ExecutorService
等多个任务,如 ForkJoinPool
如果您需要在多个任务之间进行协调, -
ExecutorService
会提供协作API。假设您必须提交N个工作任务并等待所有这些任务完成。您可以使用 invokeAll API。如果你想用多个Timer
任务实现同样的目标,那就不简单了。 -
ThreadPoolExecutor 提供更好的API来管理线程生命周期。
线程池解决了两个不同的问题:由于减少了每个任务的调用开销,它们通常在执行大量异步任务时提供更高的性能,并且它们提供了一种绑定和管理资源(包括执行时消耗的线程)的方法一系列任务。每个ThreadPoolExecutor还维护一些基本统计信息,例如已完成任务的数量
几个优点:
一个。您可以创建/管理/控制线程和生命周期。优化线程创建成本开销
湾您可以控制任务的处理(工作窃取,ForkJoinPool,invokeAll)等。
℃。您可以监视线程的进度和健康状况
d。提供更好的异常处理机制
醇>