Вопрос по java, sleep, timer, while-loop, task – Timer & TimerTask против Thread + sleep в Java

101

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

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

Точка заказа: Timer и TimerTask устарели и фактически были заменены ExecutorService, хотя ваша точка зрения остается в силе. skaffman
Спасибо за совет, я решил использовать ExecutorService :) Keshav
Спасибо всем за ответы, несомненно, дал мне больше понимания! Keshav
Timer и TimerTask по-прежнему полезны в средах JME, где ExecutorService не существует (начиная с JME Java 1.3 ...). スーパーファミコン
Таймер не устарел и предпочтителен, когда требуется только один поток. (java.sun.com/javase/6/docs/api/java/util/Timer.html) Justin

Ваш Ответ

7   ответов
1

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

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

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

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

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

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

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

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

Я нене понимаю этот аргумент. Оба варианта запускают один и тот же метод из потока, оба варианта спят в потоке, ожидая выполнения. Между этими двумя вариантами не будет различий между голодомками. satur9nine
4

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

1

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

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

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

13

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

Тот'Это очень хороший момент, спасибо. Ridcully
5

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

Таймер создает очередь задач, которая постоянно обновляется. Когда таймер сделан, он не может быть мусором сразу. Таким образом, создание большего количества таймеров только добавляет больше объектов в кучу. Thread.sleep () только приостанавливает поток, поэтому накладные расходы памяти будут чрезвычайно низкими. Darryl Gerrow
65

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

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

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
    new TimerTask() {
      public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
    }, 0, 60 * 1000);
если таймер используется для каждодневного, в 2 конкретных времени 9 вечера и 9 утра, ... как дать значения? в коде выше ... @Zed? gumuruh

Похожие вопросы