Перевага ScheduledExecutorServiceнадTimer
Я хочу запропонувати вам альтернативу Timerвикористанню - ScheduledThreadPoolExecutor , реалізація інтерфейсу ScheduledExecutorService . Він має деякі переваги перед класом Timer, згідно з "Java у паралельності":
A Timerстворює лише один потік для виконання завдань таймера. Якщо завдання таймера триває надто довго, точність синхронізації інших
TimerTaskможе постраждати. Якщо повторне TimerTaskпланується запустити кожні 10 мс, а інше завдання таймера займає 40 мс, повторюване завдання (залежно від того, чи було воно заплановане із фіксованою швидкістю або фіксованою затримкою) викликається чотири рази швидко після послідовного запущене завдання завершує або повністю «пропускає» чотири виклики. Планові пули потоків вирішують це обмеження, дозволяючи надавати декілька потоків для виконання відкладених та періодичних завдань.
Інша проблема таймера полягає в тому, що він поводиться погано, якщо TimerTask видає неперевірений виняток . Також називається "витік нитки"
Потік таймера не вловлює виняток, тому неперевірений виняток, викинутий із TimerTaskтерміна, завершує потік таймера. Таймер також не відроджує нитку в цій ситуації; натомість помилково вважається, що весь таймер було скасовано. У цьому випадку тимчасові завдання, які вже заплановані, але ще не виконуються, ніколи не запускаються, і нові завдання не можна запланувати.
І ще одна рекомендація , якщо ви хочете створити свій власний сервіс планування, ви все одно можете бути в змозі скористатися перевагами бібліотеки, використовуючи DelayQueue, в BlockingQueueреалізацію , яка забезпечує функціональні можливості диспетчеризації ScheduledThreadPoolExecutor. A DelayQueueуправляє колекцією об'єктів із затримкою. Затримка пов’язана з часом затримки: DelayQueueдозволяє взяти елемент, лише якщо його затримка минула. Об'єкти повертаються із DelayQueueзамовленого до часу, пов'язаного з їх затримкою.