Таймер и TimerTask против Thread + sleep в Java



Я нашел подобные вопросы, заданные здесь, но не было ответов на мое удовлетворение. Так что перефразируя вопрос еще раз -

у меня есть задача, которая должна осуществляться на периодической основе (скажем 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();

I действительно не нужно беспокоиться, если я пропускаю определенные циклы, если выполнение логики занимает больше времени, чем интервал.

пожалуйста, прокомментируйте это..

обновление:
Недавно я нашел еще одно различие между использованием таймера и потока.сон.)( Предположим, что текущее системное время 11:00 утра. Если мы по какой-то причине откатим системное время до 10:00, таймер перестанет выполнять задачу до тех пор, пока она не достигнет 11:00, тогда как поток.метод sleep () продолжит выполнение задача без помех. Это может быть основным лицом, принимающим решения в принятии решения о том, что использовать между этими двумя.

87   7  

7 ответов:

преимущество 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(); по телефону run() метод TimerTask в то время как другие потоки, использующие ресурсы в то же время.

Если Вы поток получить исключение и убивается, это проблема. Но TimerTask будет заботиться о нем. Он будет работать независимо от сбоя в предыдущем запуске.

Я думаю, что понимаю вашу проблему, я вижу что-то очень похожее. У меня есть таймеры, которые повторяются, некоторые каждые 30 минут и каждые пару дней. Из того, что я читаю, и комментариев, которые я вижу, похоже, что сбор мусора никогда не будет запущен, потому что все задачи никогда не будут завершены. Я бы подумал, что сбор мусора будет работать, когда таймер находится в спящем режиме, но я его не вижу и, согласно документации, это не так.

Я думаю, что создавая новые темы завершает и разрешает сбор мусора.

кто-нибудь, пожалуйста, докажите мне, что я ошибаюсь, переписывая то, что я унаследовал, будет болью.

С Timerдокументация:

Java 5.0 представил java.утиль.параллельный пакет и один из утилиты параллелизма в нем является ScheduledThreadPoolExecutor который является ли пул потоков для многократного выполнения задач с заданной скоростью или задержка. Это эффективно более универсальная замена для Комбинация Timer/TimerTask, так как она позволяет использовать несколько сервисных потоков, принимает различные единицы времени и не требует подклассов TimerTask (только реализация Runnable). Настройка ScheduledThreadPoolExecutor с одним потоком делает его эквивалентным таймеру.

Предпочитаю ScheduledThreadExecutor вместо Timer:

  • Timer использует один фоновый поток, который используется для выполнения всех задач таймера, последовательно. Поэтому задачи должны выполняться быстро, иначе это задержит выполнение последующих задач. Но в случае ScheduledThreadPoolExecutor мы можем настроить любое количество потоков, а также могут иметь полный контроль, предоставляя ThreadFactory.
  • Timer может быть чувствительным к системным часам, поскольку он использует Object.wait(long) метод. Но ScheduledThreadPoolExecutor нет.
  • исключения времени выполнения, брошенные в TimerTask, убьют этот конкретный поток, тем самым делая таймер мертвым, где мы можем справиться с этим в ScheduledThreadPoolExecutor так, что другие задачи не влияет.
  • Timer предоставляет cancel метод для завершения таймера и отбрасывания любых запланированных задач, однако это не мешает в настоящее время выполнение задачи и пусть он закончит. Но если таймер работает как поток демона, то независимо от того, отменяем мы его или нет, он завершится, как только все пользовательские потоки будут завершены.

таймер против потока.спи

таймер использует Object.wait и это отличается от Thread.sleep

  1. ждет (wait) поток может быть уведомлен (с помощью notify) другим потоком, но спящий не может быть, это может быть только прерванный.
  2. ожидание (и уведомление) должно происходить в блоке, синхронизированном на объекте монитора, тогда как сон не происходит.
  3. во время сна не освобождает блокировку, ожидание освободит блокировку для объекта ожидание вызывается.
    Ничего не найдено.

Добавить ответ:
Отменить.