我有代码,我使用java.util.Timer
. 我环顾四周,看到ExecutorService
可以做同样的事情。所以这里的这个问题,你有没有使用Timer
和ExecutorService
安排任务,一个使用比另一个有什么好处?
还想检查是否有人使用过该Timer
课程并遇到ExecutorService
为他们解决的任何问题。
我有代码,我使用java.util.Timer
. 我环顾四周,看到ExecutorService
可以做同样的事情。所以这里的这个问题,你有没有使用Timer
和ExecutorService
安排任务,一个使用比另一个有什么好处?
还想检查是否有人使用过该Timer
课程并遇到ExecutorService
为他们解决的任何问题。
根据实践中的Java并发:
Timer
可以对系统时钟的变化敏感,ScheduledThreadPoolExecutor
不是。Timer
只有一个执行线程,所以长时间运行的任务会延迟其他任务。ScheduledThreadPoolExecutor
可以配置任意数量的线程。此外,如果需要(通过提供ThreadFactory
),您可以完全控制创建的线程。TimerTask
杀死一个线程,从而使Timer
死:-( ... 即计划任务将不再运行。ScheduledThreadExecutor
不仅捕获运行时异常,而且它允许您在需要时处理它们(通过覆盖afterExecute
方法 from 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
(即它将是单线程的)类似的功能,但其访问可能更具可扩展性(在后台,它使用并发结构而不是与Timer
类完全同步)。使用 aScheduledExecutorService
还可以为您带来以下优势:
newScheduledThreadPoolExecutor()
或ScheduledThreadPoolExecutor
类)Timer
关于我能想到的坚持的唯一原因是:
ExecutorService 更新更通用。计时器只是一个定期运行您为其安排的内容的线程。
ExecutorService 可能是一个线程池,甚至可以分布在集群中的其他系统中,并执行一次性批量执行等操作...
看看每个提供什么来决定。
以下是有关计时器使用的更多良好实践:
http://tech.puredanger.com/2008/09/22/timer-rules/
一般来说,我会使用 Timer 来处理快速而肮脏的东西,而使用 Executor 来获得更强大的使用。
来自ScheduledThreadPoolExecutor上的 Oracle 文档页面
一个ThreadPoolExecutor,可以额外安排命令在给定延迟后运行,或定期执行。当需要多个工作线程时,或者需要额外的灵活性或 ThreadPoolExecutor(此类扩展)的功能时,此类比Timer更可取。
ExecutorService/ThreadPoolExecutor
或者ScheduledThreadPoolExecutor
当您有多个工作线程时是明显的选择。
ExecutorService
结束的优点Timer
Timer
不能利用可用的 CPU 内核,这与 使用ForkJoinPool之类ExecutorService
的多任务的情况不同ExecutorService
ExecutorService
如果您需要在多个任务之间进行协调,则提供协作 API。假设您必须提交 N 个工作任务并等待所有任务完成。您可以使用invokeAll API 轻松实现它。如果您想通过多个Timer
任务实现相同的目标,那就不简单了。ThreadPoolExecutor为管理线程生命周期提供了更好的 API。
线程池解决了两个不同的问题:由于减少了每个任务的调用开销,它们通常在执行大量异步任务时提供改进的性能,并且它们提供了一种限制和管理资源的方法,包括执行一组线程时消耗的线程。任务。每个 ThreadPoolExecutor 还维护一些基本的统计信息,例如完成任务的数量
几个优点:
一种。您可以创建/管理/控制线程的生命周期并优化线程创建成本开销
湾。您可以控制任务的处理(Work Stealing、ForkJoinPool、invokeAll)等。
C。您可以监控线程的进度和健康状况
d。提供更好的异常处理机制
我有时更喜欢 Timer 而不是 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 的健壮性时,我会这样做。
我确实遇到了 Timer 问题,我用 ScheduledExecutorService替换它来修复它。
问题是计时器取决于系统时间,每次我更改它时,它都会影响应用程序的功能。所以我用ScheduledExecutorService替换了Timer ,现在它工作正常。