1. Executor

Executor – базовий інтерфейс для класів, що реалізує запуск Runnable завдань. Тим самим забезпечується допомога з додаванням завдання та способом її запуску.

ExecutorService – інтерфейс, що розширює властивості Executor і який описує сервіс для запуску Runnable або Callable завдань. Методи submit на вхід приймають завдання у вигляді Callable або Runnable, а як значення, що повертається йде Future, через який ти можеш отримати результат.

Метод invokeAll відповідає за виконання завдань з поверненням списку завдань зі своїм статусом та результатами завершення.

Метод invokeAny відповідає за виконання завдань з поверненням результату успішно виконаної задачі (тобто без створення винятку), якщо такі є.

ScheduledExecutorService – цей інтерфейс додає можливість запускати відкладені завдання з певною затримкою або певним періодом.

AbstractExecutorService – абстрактний клас для побудови ExecutorService. Усередині є імплементація методів submit, invokeAll,invokeAny. Від цього класу успадковуються ThreadPoolExecutor, ScheduledThreadPoolExecutor та ForkJoinPool.


public static void main(String[] args) {
   ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
   Callable<String> task = () -> {
       System.out.println(Thread.currentThread().getName());
       return Thread.currentThread().getName();
   };
   scheduledExecutorService.schedule(task, 10, TimeUnit.SECONDS);
   scheduledExecutorService.shutdown();
}

2. ThreadPoolExecutor

Executors – клас-фабрика для створення ThreadPoolExecutor, ScheduledThreadPoolExecutor. Якщо потрібно створити один із цих пулів, то ця фабрика саме те, що потрібно. Містяться різні адаптери Runnable-Callable, PrivilegedAction-Callable, PrivilegedExceptionAction-Callable та інші. Має статичні методи для створення різних ThreadPool.

ThreadPoolExecutor – реалізує інтерфейси Executor і ExecutorService та рзділяє створення задачі та її виконання. Нам необхідно реалізувати об'єкти Runnable та надіслати їх виконавцю, а ThreadPoolExecutor відповідає за їх виконання, створення екземплярів та роботу з потоками.

ScheduledThreadPoolExecutor – на додаток до методів ThreadPoolExecutor створює пул потоків, який може планувати виконання команд після встановленої затримки або для періодичного виконання.

ThreadFactory – це об'єкт, який створює нові потоки на вимогу. Нам необхідно передати екземпляр метод Executors.newSingleThreadExecutor(ThreadFactory threadFactory).


ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
 @Override public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "MyThread");
thread.setPriority(Thread.MAX_PRIORITY);
 return thread; }
 });

RejectedExecutionHandler – дозволяє визначити обробник для завдань, які з певних причин не можуть бути виконані через ThreadPoolExecutor. Таке відбувається, коли немає вільних потоків, сервіс вимикається чи вимкнений (shutdown).

Декілька стандартних імплементацій знаходяться в класі ThreadPoolExecutor:

  • CallerRunsPolicy – запускає завдання в потоці, що викликає;
  • AbortPolicy – кидає ексепшен;
  • DiscardPolicy – ігнорує завдання;
  • DiscardOldestPolicy – видаляє найстаріше незапущене завдання з черги, потім намагається додати нове завдання ще раз.

3. Completion Service

CompletionService – інтерфейс сервісу з розв'язкою запуску асинхронних завдань та отриманням результатів. Для додавання задач є метод submit, а для отримання результатів вже завершених задач використовується блокуючий метод take та неблокуючий poll.

ExecutorCompletionService – це обгортка над будь-яким класом, який реалізує інтерфейс Executor, наприклад,ThreadPoolExecutor або ForkJoinPool. Використовується, коли потрібно абстрагуватися від способу запуску завдань та контролю за їх виконанням.

Якщо є завершені завдання, витягуємо їх. Якщо завдань немає, то висимо в take, поки що-небудь завершиться. В основі сервісу використовується LinkedBlockingQueue, але ти можеш передати будь-яку реалізацію BlockingQueue.