Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
定时器和;TimerTask与线程+;在Java中睡觉_Java_Timer_While Loop_Sleep_Task - Fatal编程技术网

定时器和;TimerTask与线程+;在Java中睡觉

定时器和;TimerTask与线程+;在Java中睡觉,java,timer,while-loop,sleep,task,Java,Timer,While Loop,Sleep,Task,我在这里发现了类似的问题,但没有让我满意的答案。那么,重新表述一下这个问题- 我有一项任务需要定期完成(比如每隔1分钟)。使用Timertask&Timer来实现这一点,与创建具有无限循环的睡眠的新线程相比,有什么优势 使用timertask的代码段- TimerTask uploadCheckerTimerTask = new TimerTask(){ public void run() { NewUploadServer.getInstance().checkAndUploadFil

我在这里发现了类似的问题,但没有让我满意的答案。那么,重新表述一下这个问题-

我有一项任务需要定期完成(比如每隔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);
使用线程和睡眠的代码段-

Thread t = new Thread(){
 public void run() {
  while(true) {
   NewUploadServer.getInstance().checkAndUploadFiles();
   Thread.sleep(60 * 1000);
  }
 }
};
t.start();
如果逻辑的执行时间超过了间隔时间,我真的不必担心是否错过了某些周期

请对此发表评论

更新:

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

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

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

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

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

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


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

我不知道为什么,但我正在编写的一个程序使用计时器,它的堆大小不断增加,一旦我把它改为线程/睡眠,问题就解决了。

如果线程发生异常并被杀死,这就是一个问题。
但TimerTask会处理好的。无论上次运行是否失败,它都将运行。

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

我认为生成新线程就完成了,并允许垃圾收集


有人请证明我错了,重写我继承的东西将是一件痛苦的事。

来自
计时器

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

因此,首选
ScheduledThreadExecutor
而不是
Timer

  • Timer
    使用单个后台线程,用于按顺序执行计时器的所有任务。因此,任务应该快速完成,否则会延迟后续任务的执行。但是在
    ScheduledThreadPoolExecutor
    的情况下,我们可以配置任意数量的线程,也可以通过提供
    ThreadFactory
    进行完全控制
  • 定时器可以对系统时钟敏感,因为它使用了
    对象。等待(长)
    方法。但是
    ScheduledThreadPoolExecutor
    不是
  • TimerTask中抛出的运行时异常将杀死该特定线程,从而使我们可以在
    ScheduledThreadPoolExecutor
    中处理该线程的地方导致计时器死机,从而不会影响其他任务
  • Timer
    提供了
    cancel
    方法来终止计时器并放弃任何计划任务,但是它不会干扰当前正在执行的任务并让其完成。但如果计时器作为守护进程线程运行,那么无论我们是否取消它,它都将在所有用户线程完成执行后立即终止
计时器与线程睡眠 计时器使用
对象。wait
,它不同于
线程。sleep

  • 等待(
    wait
    )线程可以被另一个线程通知(使用
    notify
    ),但睡眠线程不能,只能被中断
  • 等待(和通知)必须在监视器对象上同步的块中发生,而睡眠不会发生
  • 睡眠不会释放锁,等待会释放锁,因为调用了对象wait

  • 规程问题:计时器和TimerTask已经过时,并且已经被ExecutorService有效地取代,尽管您的观点仍然有效。感谢您的提示,我决定使用ExecutorService:)谢谢您的回答,肯定让我更加理解!计时器不是过时的,更可取