Вопрос

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

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

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

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

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

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

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

Java 5.0 представила пакет java.util.concurrent, и одна из утилит для параллелизма в нем представляет собой планируемыйЭто фактически более универсальная замена для комбинации таймера/Timertask, поскольку она позволяет нескольким потокам обслуживания, принимает различные временные единицы и не требует подкласса Timertask (просто реализуйте runnable).Настройка galduldThreadPoolexeCutor с одним потоком делает его эквивалентным для таймера.

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top