Ще один тип пулу потоків — пул запланованих завдань. Судячи з назви можна припустити, що ми використовуємо цей тип для планування запуску певного завдання, рознесеного в часі.
Цей вид сервісу стає в нагоді, коли ми маємо запустити певну активність з умовою закінчення певного часу або періодичності виконання такого завдання.
Щоб використати такий сервіс, ми викликаємо Executors.newScheduledThreadPool(1).
Про параметри поговоримо трохи згодом: зараз важливо розуміти, що при виклику цього методу нам повертається об'єкт типу ScheduledExecutorService.
ScheduledExecutorService — це інтерфейс, успадкований від ExecutorService.
У цьому інтерфейсі з'являються такі методи:
Метод | Пояснення |
---|---|
|
Створює та виконує одноразову дію, яка реалізується після заданої затримки. |
|
Створює та виконує об'єкт ScheduledFuture, який реалізується після заданої затримки. |
|
Створює та виконує періодичну дію, яка реалізується спочатку після заданої початкової затримки, а потім – із заданим періодом. Отже, виконання почнеться після initialDelay, потім initialDelay+period, theninitialDelay + 2 * period тощо. |
|
Створює та виконує періодичну дію, яка реалізується спочатку після даної початкової затримки, а потім із заданою затримкою між завершенням одного виконання та початком наступного. |
Як ми бачимо, інтерфейс надає можливість запуску завдань із періодичністю або через якийсь час.
Далі про метод newScheduledThreadPool.
Викликати ми його можемо кількома способами:
|
corePoolSize — кількість потоків, які потрібно зберігати в пулі, навіть якщо вони простоюють. |
|
corePoolSize — кількість потоків, які потрібно зберігати в пулі, навіть якщо вони простоюють. threadFactory — фабрика, що використовується при створенні нових потоків. |
Обидва методи створять пул потоків, який може планувати виконання команд після заданої затримки або для періодичного виконання.
Давайте розглянемо роботу ScheduledThreadPool на прикладі.
Припустимо, у нас є завдання перевіряти пошту кожні 5 секунд, водночас ця перевірка не повинна впливати на роботу основної програми і несе за собою можливе додаткове споживання ресурсів.
У нас є клас завдання, що моделює перевірку пошти.
public class Task implements Runnable {
@Override
public void run() {
System.out.println("Перевіряємо пошту...");
}
}
Далі ми створюємо пул потоків та встановлюємо розклад для виконання перевірки.
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
executorService.scheduleAtFixedRate(new Task(), 0, 5, TimeUnit.SECONDS);
У виведенні ми бачимо кожні 5 секунд:
Загалом такий пул, як у в прикладі, ми можемо використовувати для виконання “сервісних” періодичних завдань. Сервісними ми називаємо ті завдання, які потрібно виконати незалежно від роботи основного функціоналу програми.