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