Java 中的 Timer & TimerTask 与 Thread + sleep

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1453295/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 12:26:25  来源:igfitidea点击:

Timer & TimerTask versus Thread + sleep in Java

javatimerwhile-loopsleeptask

提问by Keshav

I found similar questions asked here but there weren't answers to my satisfaction. So rephrasing the question again-

我发现这里有类似的问题,但没有让我满意的答案。所以再次改写这个问题——

I have a task that needs to be done on a periodic basis (say 1 minute intervals). What is advantage of using Timertask & Timer to do this as opposed to creating a new thread that has a infinite loop with sleep?

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

Code snippet using timertask-

使用 timertask 的代码片段-

TimerTask uploadCheckerTimerTask = new TimerTask(){

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

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(uploadCheckerTimerTask, 0, 60 * 1000);

Code snippet using Thread and sleep-

使用线程和睡眠的代码片段-

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

I really don't have to worry if I miss certain cycles if the execution of the logic takes more than the interval time.

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

Please comment on this..

请对此发表评论..

Update:
Recently I found another difference between using Timer versus Thread.sleep(). Suppose the current system time is 11:00AM. If we rollback the system time to 10:00AM for some reason, The Timer will STOP executing the task until it has reached 11:00AM, whereas Thread.sleep() method would continue executing the task without hindrance. This can be a major decision maker in deciding what to use between these two.

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

采纳答案by Zed

The advantage of TimerTask is that it expresses your intention much better (i.e. code readability), and it already has the cancel() feature implemented.

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

Note that it can be written in a shorter form as well as your own example:

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

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

回答by MartinStettner

Timer/TimerTask also takes into account the execution time of your task, so it will be a bit more accurate. And it deals better with multithreading issues (such as avoiding deadlocks etc.). And of course it is usually better to use well-tested standard code instead of some homemade solution.

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

回答by Boris Pavlovi?

There's one crucial argument against managing this task using Java threads and sleepmethod. You are using while(true)to stay indefinitely in the loop and hibernate the thread by putting to sleep. What if NewUploadServer.getInstance().checkAndUploadFiles();takes up some synchronized resources. Other threads will be unable to access these resources, starvation may happen which can slow down your whole application. These kinds of errors are hard to diagnose and it's a good idea to prevent their existance.

有一个反对使用 Java 线程和sleep方法管理此任务的关键论点。您正在使用while(true)无限期地留在循环中并通过进入睡眠状态来休眠线程。如果NewUploadServer.getInstance().checkAndUploadFiles();占用了一些同步资源怎么办。其他线程将无法访问这些资源,可能会发生饥饿,这会降低整个应用程序的速度。这些类型的错误很难诊断,最好阻止它们的存在。

The other aproach triggers the execution of the code that matters to you, i.e. NewUploadServer.getInstance().checkAndUploadFiles();by calling the run()method of your TimerTaskwhile letting other threads using the resources in the meanwhile.

另一种方法触发对您重要的代码的执行,即NewUploadServer.getInstance().checkAndUploadFiles();通过调用run()您的方法TimerTask同时让其他线程使用资源。

回答by Qandeel

I don't know why but a program that I was writing was using Timers and it's heap size was increasing constantly, once I changed it to Thread/sleep problem solved.

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

回答by Stack Popper

If you thread get exception and gets killed, that is a problem. But TimerTask will take care of it. It will run irrespective of failure in previous run.

如果您的线程获得异常并被杀死,那就是一个问题。但是 TimerTask 会处理它。无论上次运行是否失败,它都会运行。

回答by Ken

I think I understand your issue, I am seeing something very similar. I have timers that are recurring, some every 30 minutes and some every couple of days. From what I read and the comments I see, it looks like garbage collection will never run because all the task are never complete. I would think that garbage collection would run when a timer is in sleep, but I am not seeing it and according to the documentation it does not.

我想我理解你的问题,我看到了非常相似的东西。我有重复的计时器,有些是每 30 分钟一次,有些是每两天一次。从我阅读的内容和我看到的评论来看,垃圾收集似乎永远不会运行,因为所有任务都永远不会完成。我认为垃圾收集会在计时器处于睡眠状态时运行,但我没有看到它,并且根据文档它没有看到。

I think that spawning new threads completes and allow garbage collection.

我认为产生新线程完成并允许垃圾收集。

Someone please prove me wrong, rewriting what I inherited is going to be a pain.

有人请证明我错了,重写我继承的东西会很痛苦。

回答by akhil_mittal

From the Timerdocumentation:

Timer文档

Java 5.0 introduced the java.util.concurrent package and one of the concurrency utilities therein is the ScheduledThreadPoolExecutor which is a thread pool for repeatedly executing tasks at a given rate or delay. It is effectively a more versatile replacement for the Timer/TimerTask combination, as it allows multiple service threads, accepts various time units, and doesn't require subclassing TimerTask (just implement Runnable). Configuring ScheduledThreadPoolExecutor with one thread makes it equivalent to Timer.

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

So Prefer ScheduledThreadExecutorinstead of Timer:

所以更喜欢ScheduledThreadExecutor而不是Timer

  • Timeruses single background thread that is used to execute all of the timer's tasks, sequentially. So tasks should complete quickly else it will delay the execution of subsequent tasks. But in case of ScheduledThreadPoolExecutorwe can configure any number of threads and can also have full control by providing ThreadFactory.
  • Timercan be sensitive to system clock as it makes use of Object.wait(long)method. But ScheduledThreadPoolExecutoris not.
  • Runtime exceptions thrown in TimerTask will kill that particular thread, thus making Timer dead where as we can handle that in ScheduledThreadPoolExecutorso that the other tasks are not impacted.
  • Timerprovides cancelmethod to terminate the timer and discard any scheduled tasks, however it doesn't interfere with the currently executing task and let it finish. But if timer is running as daemon thread then whether we cancel it or not, it will terminate as soon as all the user threads are finished executing.
  • Timer使用单个后台线程,用于按顺序执行所有计时器的任务。所以任务应该尽快完成,否则会延迟后续任务的执行。但在这种情况下,ScheduledThreadPoolExecutor我们可以配置任意数量的线程,也可以通过提供ThreadFactory.
  • Timer可以对系统时钟敏感,因为它使用Object.wait(long)方法。但ScheduledThreadPoolExecutor不是。
  • 在 TimerTask 中抛出的运行时异常将杀死该特定线程,从而使 Timer 在我们可以处理的地方死亡,ScheduledThreadPoolExecutor以便其他任务不受影响。
  • Timer提供cancel终止计时器并丢弃任何计划任务的方法,但它不会干扰当前正在执行的任务并让它完成。但是如果计时器作为守护线程运行,那么无论我们是否取消它,它都会在所有用户线程执行完毕后立即终止。

Timer vs Thread.sleep

定时器与 Thread.sleep

Timer makes use of Object.waitand it is different from Thread.sleep

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

  1. A waiting (wait) thread can be notified (using notify) by another thread but a sleeping one cannot be, it can only be interrupted.
  2. A wait (and notify) must happen in a block synchronized on the monitor object whereas sleep does not.
  3. While sleeping does not release the lock, waiting will release the lock for the object wait is called upon.
  1. 等待 ( wait) 线程可以被notify另一个线程通知 (使用),但睡眠线程不能,只能被中断。
  2. 等待(和通知)必须在监视器对象上同步的块中发生,而睡眠则没有。
  3. 虽然 sleep 不会释放锁,但waiting 会释放锁,以便调用wait 的对象。