我发现这里问类似的问题,但有没有答案让我满意。 因此改写再次 - 问题
我有一个需要定期执行的任务(比如说1个分钟间隔)。 什么是优势利用的TimerTask和定时器要做到这一点,而不是创造具有与睡眠无限循环一个新的线程?
使用代码片断timertask-
TimerTask uploadCheckerTimerTask = new TimerTask(){
public void run() {
NewUploadServer.getInstance().checkAndUploadFiles();
}
};
Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(uploadCheckerTimerTask, 0, 60 * 1000);
代码段使用线程和睡眠 -
Thread t = new Thread(){
public void run() {
while(true) {
NewUploadServer.getInstance().checkAndUploadFiles();
Thread.sleep(60 * 1000);
}
}
};
t.start();
我真的不担心,如果我错过一定周期,如果逻辑的执行时间比间隔时间更多。
在此请评论..
更新:
最近我发现,使用定时器与Thread.sleep()方法的另一个区别。 假设当前的系统时间是11:00。 如果我们回滚系统时间10:00 AM出于某种原因,定时器将停止执行任务,直到它达到11:00,而Thread.sleep()方法的方法将继续不受阻碍地执行任务。 这可能是在决定这两者之间用什么主要的决策者。
TimerTask的的优势在于它表达你的意图更好(即代码的可读性),它业已实施的取消()功能。
需要注意的是它可以在更短的形式被写入,以及你自己的例子:
Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
new TimerTask() {
public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
}, 0, 60 * 1000);
定时器/ TimerTask的也考虑到你的任务的执行时间,所以这将是一个位更准确。 而且它涉及多线程问题(如避免死锁等)效果更佳。 当然,它通常是更好地使用,而不是一些自制的解决方案以及测试标准代码。
我不知道为什么,但使用定时器,我是写一个程序是,它的堆大小不断增加,一旦我改成了主题/睡眠问题解决了。
如果线程获得例外,就会被杀死,这是一个问题。 但TimerTask的会照顾它。 它将以前的运行,不论失败的运行。
有对管理使用Java线程和这个任务一个关键参数sleep
方法。 您正在使用while(true)
留在无限期的循环,通过把睡觉休眠线程。 如果NewUploadServer.getInstance().checkAndUploadFiles();
占用了一些同步的资源。 其他线程将无法访问这些资源,饥饿可能发生可以减缓你的整个应用程序。 这些类型的错误是很难诊断,它是为了防止他们的所有脑干是个好主意。
其他的形式给出了触发对你很重要,即代码的执行NewUploadServer.getInstance().checkAndUploadFiles();
通过调用run()
你的方法TimerTask
同时让使用资源的同时其他线程。
我想我明白你的问题,我看到一些非常相似。 我有一个是重复,有的每30分钟和一些每隔几天定时器。 从我读和意见,我看,它看起来像垃圾收集永远不会运行,因为所有的任务都永远不会完成。 我想,当计时器处于休眠垃圾收集会跑,但我没有看到它,并根据它不是文档。
我认为,产生新的线程完成,并允许垃圾收集。
有人请证明我错了,重写我的继承将是一个痛苦。
从Timer
文档 :
爪哇5.0引入java.util.concurrent包和的并发性实用程序之一是在其中它是在给定速率或延迟反复执行任务的线程池的ScheduledThreadPoolExecutor。 这实际上是对定时器/ TimerTask的组合更灵活的替代品,因为它允许多个服务线程,接受各种时间单位,并且不需要TimerTask的子类(只实现Runnable)。 配置的ScheduledThreadPoolExecutor使用一个线程使其等同于定时器。
所以身高ScheduledThreadExecutor
而不是Timer
:
-
Timer
使用,用于执行所有的计时器的任务,顺序单后台线程。 所以任务应该完成别人很快就会耽误后续任务的执行。 但在案件ScheduledThreadPoolExecutor
可以配置任何数量的线程,也可以通过提供具有完全控制ThreadFactory
。 -
Timer
,因为它利用了可以是系统时钟敏感Object.wait(long)
方法。 但是ScheduledThreadPoolExecutor
不是。 - 在TimerTask的抛出运行时异常会杀了那个特定的线程,从而使定时器死在那里,我们可以处理,在
ScheduledThreadPoolExecutor
这样其他任务不受影响。 -
Timer
提供cancel
方法来终止计时器,并丢弃任何计划的任务,但它不与当前正在执行的任务的干扰,让它完成。 但是,如果定时器运行为守护线程那么我们是否要取消它与否,会尽快的所有用户线程都执行完毕后终止。
定时器VS了Thread.sleep
计时器利用了Object.wait
,它是从不同Thread.sleep
- 等待(
wait
)线程(使用通知notify
由另一个线程),但睡眠一个不能,它只能被中断。 - 而睡眠不甲等待(和通知)必须在显示器上的对象同步的块发生。
- 睡觉时不解除锁定,等待将发布对象等待时被称为锁。