Подтвердить что ты не робот

Timer & TimerTask против темы + спать в Java

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

У меня есть задача, которую необходимо выполнять периодически (скажем, с интервалом в 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 и sleep-

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

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

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

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

4b9b3361

Ответ 1

Преимущество TimerTask заключается в том, что он значительно улучшает ваше намерение (то есть читаемость кода), и у него уже есть функция cancel().

Обратите внимание, что его можно записать в более короткой форме, а также в вашем собственном примере:

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

Ответ 2

Timer/TimerTask также учитывает время выполнения вашей задачи, поэтому он будет немного более точным. И он лучше справляется с проблемами многопоточности (например, избегая взаимоблокировок и т.д.). И, конечно, обычно лучше использовать проверенный стандартный код вместо некоторого домашнего решения.

Ответ 3

Я не знаю, почему, но программа, которую я пишу, использовала таймеры, и размер кучи постоянно увеличивался, как только я изменил ее на проблему Thread/sleep.

Ответ 4

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

Ответ 5

Из Timer документации:

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

Поэтому предпочтите 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. В то время как сон не снимает блокировку, ожидание освободит блокировку для вызова объекта wait.

Ответ 6

Есть один важный аргумент против управления этой задачей с использованием потоков Java и метода sleep. Вы используете while(true), чтобы оставаться неопределенно в цикле и спящий поток, укладывая спать. Что делать, если NewUploadServer.getInstance().checkAndUploadFiles(); использует некоторые синхронизированные ресурсы. Другие потоки не смогут получить доступ к этим ресурсам, может произойти голод, который может замедлить все ваше приложение. Такие ошибки трудно диагностировать, и это хорошая идея, чтобы предотвратить их существование.

Другой aproach запускает выполнение кода, который имеет для вас значение, т.е. NewUploadServer.getInstance().checkAndUploadFiles();, вызывая метод run() вашего TimerTask, позволяя другим потокам использовать ресурсы в то же время.

Ответ 7

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

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

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