Timer中的Timer&TimerTask与Thread + sleep

Kes*_*hav 103 java sleep timer task while-loop

我在这里发现了类似的问题,但没有我满意的答案.所以再次重述这个问题 -

我有一项需要定期完成的任务(比如每隔1分钟).使用Timertask&Timer执行此操作的优势是什么,而不是创建一个具有无限循环睡眠的新线程?

使用timertask-的代码段 -

TimerTask uploadCheckerTimerTask = new TimerTask(){

 public void run() {
  NewUploadServer.getInstance().checkAndUploadFiles();
 }
};

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(uploadCheckerTimerTask, 0, 60 * 1000);
Run Code Online (Sandbox Code Playgroud)

使用Thread和sleep的代码片段 -

Thread t = new Thread(){
 public void run() {
  while(true) {
   NewUploadServer.getInstance().checkAndUploadFiles();
   Thread.sleep(60 * 1000);
  }
 }
};
t.start();
Run Code Online (Sandbox Code Playgroud)

如果逻辑执行时间超过间隔时间,我真的不必担心是否会错过某些周期.

请评论这个..

更新:
最近我发现使用Timer与Thread.sleep()之间存在另一个区别.假设当前系统时间是上午11:00.如果由于某种原因我们将系统时间回滚到上午10:00,则计时器将停止执行任务,直到它到达上午11:00,而Thread.sleep()方法将继续执行任务而不受阻碍.这可能是决定在这两者之间使用什么的主要决策者.

Zed*_*Zed 67

TimerTask的优点在于它更好地表达了您的意图(即代码可读性),并且已经实现了cancel()功能.

请注意,它可以用更短的形式和您自己的示例编写:

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
    new TimerTask() {
      public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
    }, 0, 60 * 1000);
Run Code Online (Sandbox Code Playgroud)


Mar*_*ner 13

Timer/TimerTask还会考虑任务的执行时间,因此它会更准确一些.它更好地处理多线程问题(例如避免死锁等).当然,通常使用经过充分测试的标准代码而不是一些自制的解决方案会更好.


i_a*_*ero 7

Timer 文档

Java 5.0 引入了 java.util.concurrent 包,其中的并发实用程序之一是 ScheduledThreadPoolExecutor,它是一个线程池,用于以给定的速率或延迟重复执行任务。它实际上是 Timer/TimerTask 组合的更通用的替代品,因为它允许多个服务线程,接受各种时间单位,并且不需要子类化 TimerTask(只需实现 Runnable)。使用一个线程配置 ScheduledThreadPoolExecutor 使其等效于 Timer。

所以更喜欢ScheduledThreadExecutor而不是Timer

  • Timer使用单个后台线程,用于按顺序执行所有计时器的任务。所以任务应该尽快完成,否则会延迟后续任务的执行。但在这种情况下,ScheduledThreadPoolExecutor我们可以配置任意数量的线程,也可以通过提供ThreadFactory.
  • Timer可以对系统时钟敏感,因为它使用Object.wait(long)方法。但ScheduledThreadPoolExecutor不是。
  • 在 TimerTask 中抛出的运行时异常将杀死该特定线程,从而使 Timer 在我们可以处理的地方死亡,ScheduledThreadPoolExecutor以便其他任务不受影响。
  • Timer提供cancel终止计时器并丢弃任何计划任务的方法,但它不会干扰当前正在执行的任务并让它完成。但是如果计时器作为守护线程运行,那么无论我们是否取消它,一旦所有用户线程执行完毕,它就会终止。

定时器与 Thread.sleep

定时器利用Object.wait和它不同Thread.sleep

  1. 等待 ( wait) 线程可以被notify另一个线程通知 (使用),但睡眠线程不能,只能被中断。
  2. 等待(和通知)必须在监视器对象上同步的块中发生,而睡眠则没有。
  3. 虽然 sleep 不会释放锁,但waiting 会为调用wait 的对象释放锁。


小智 5

我不知道为什么,但是我正在编写的程序正在使用Timers,并且它的堆大小不断增加,一旦我将其更改为线程/睡眠问题已解决.

  • Timer创建一个不断更新的任务队列.Timer完成后,可能不会立即进行垃圾回收.因此,创建更多Timers只会在堆上添加更多对象.Thread.sleep()只会暂停线程,因此内存开销会非常低. (9认同)