Я нашел здесь похожие вопросы, но не получил удовлетворительных ответов. Итак, перефразируя вопрос еще раз -
У меня есть задача, которую нужно выполнять периодически (скажем, с интервалом в 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 / TimerTask также учитывает время выполнения вашей задачи, поэтому оно будет немного точнее. И он лучше справляется с проблемами многопоточности (такими как предотвращение взаимоблокировок и т. Д.). И, конечно, обычно лучше использовать проверенный стандартный код вместо какого-то самодельного решения.
источник
Я не знаю почему, но программа, которую я писал, использовала таймеры, и размер кучи постоянно увеличивался, как только я изменил его на проблему с потоком / сном, решена.
источник
Если вы получаете исключение и убиваете поток, это проблема. Но TimerTask позаботится об этом. Он будет работать независимо от сбоя в предыдущем запуске.
источник
Из
Timer
документации :Так что предпочитайте
ScheduledThreadExecutor
вместоTimer
:Timer
использует один фоновый поток, который используется для последовательного выполнения всех задач таймера. Таким образом, задачи должны выполняться быстро, иначе это приведет к задержке выполнения последующих задач. Но в случае, еслиScheduledThreadPoolExecutor
мы можем настроить любое количество потоков, а также можем иметь полный контроль, предоставивThreadFactory
.Timer
может быть чувствительным к системным часам, поскольку используетObject.wait(long)
метод. НоScheduledThreadPoolExecutor
нет.ScheduledThreadPoolExecutor
чтобы не затронуть другие задачи.Timer
предоставляетcancel
метод для завершения таймера и отмены любых запланированных задач, однако он не мешает текущей выполняемой задаче и позволяет ей завершиться. Но если таймер работает как поток демона, то, отменяем мы его или нет, он завершится, как только все пользовательские потоки закончат выполнение.Таймер против Thread.sleep
Таймер использует,
Object.wait
и он отличается отThread.sleep
wait
) может быть уведомлен (использованnotify
) другим потоком, но спящий не может быть, его можно только прервать.источник
Есть один важный аргумент против управления этой задачей с помощью потоков и
sleep
методов Java . Вы используете,while(true)
чтобы оставаться в цикле на неопределенное время и перевести поток в спящий режим. Что, еслиNewUploadServer.getInstance().checkAndUploadFiles();
потребует синхронизированных ресурсов. Другие потоки не смогут получить доступ к этим ресурсам, может произойти голодание, которое может замедлить работу всего приложения. Ошибки такого типа сложно диагностировать, и рекомендуется предотвратить их появление.Другой aproach запускает выполнение кода, который важен для вас, то есть
NewUploadServer.getInstance().checkAndUploadFiles();
путем вызоваrun()
вашего методаTimerTask
, позволяя тем временем другим потокам использовать ресурсы.источник
Я думаю, что понимаю вашу проблему, я вижу нечто очень похожее. У меня есть таймеры, которые повторяются, некоторые каждые 30 минут, а некоторые каждые пару дней. Из того, что я читал, и из комментариев, которые я вижу, похоже, что сборка мусора никогда не будет запущена, потому что все задачи никогда не завершаются. Я бы подумал, что сборка мусора будет запускаться, когда таймер находится в спящем режиме, но я этого не вижу, и, согласно документации, этого не происходит.
Я думаю, что создание новых потоков завершено и разрешена сборка мусора.
Кто-нибудь, пожалуйста, докажите, что я неправ, переписывать то, что я унаследовал, будет болью.
источник