Innym typem puli wątków jest pula zaplanowanych zadań. Sądząc po nazwie, możemy przypuszczać, że używamy tego typu do planowania uruchomienia określonego zadania, rozłożonego w czasie.

Ten rodzaj usługi jest przydatny, gdy mamy zadanie uruchomienia czynności pod warunkiem, że upłynął jakiś czas lub zadanie jest zaplanowane do okresowego uruchamiania.

Aby użyć, wywołujemy Executors.newScheduledThreadPool(1) .

O parametrach porozmawiamy nieco później, teraz ważne jest, abyśmy zrozumieli, że po wywołaniu tej metody zwracany jest do nas obiekt typu ScheduledExecutorService .

ScheduledExecutorService to interfejs dziedziczony z ExecutorService .

W tym interfejsie pojawiają się następujące metody:

metoda Wyjaśnienie

ScheduledFuture<?>
schedule(Runnable command,
                                  long delay, TimeUnit unit);
Tworzy i wykonuje jednorazową akcję, która jest uruchamiana po określonym opóźnieniu.

<V> ScheduledFuture<V>
schedule(Callable<V> callable,
                                      long delay, TimeUnit unit);
Tworzy i wykonuje obiektZaplanowana przyszłość, która jest wykonywana po określonym opóźnieniu.

ScheduledFuture<?>
scheduleAtFixedRate(Runnable command,
                                             long initialDelay,
                                             long period,
                                             TimeUnit unit);
Tworzy i wykonuje akcję okresową, która jest uruchamiana najpierw po określonym opóźnieniu początkowym, a następnie w określonym okresie; tj. wykonanie rozpocznie się po initialDelay , następnie initialDelay+period , theninitialDelay + 2 * kropka i tak dalej.

ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                long initialDelay,
                                                long delay,
                                                TimeUnit unit);
Tworzy i wykonuje akcję okresową, która jest wykonywana najpierw po określonym początkowym opóźnieniu, a następnie z określonym opóźnieniem między zakończeniem jednego wykonania a rozpoczęciem następnego.

Jak widzimy, interfejs daje nam możliwość uruchamiania zadań w regularnych odstępach czasu lub po pewnym czasie.

Więcej o metodzie newScheduledThreadPool.

Możemy to nazwać na kilka sposobów:


newScheduledThreadPool(int corePoolSize)
corePoolSize to liczba wątków, które mają pozostać w puli, nawet jeśli są bezczynne.

newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)

corePoolSize to liczba wątków, które mają pozostać w puli, nawet jeśli są bezczynne.

ThreadFactory to fabryka używana podczas tworzenia nowych wątków.

Obie metody utworzą pulę wątków, które mogą planować wykonywanie poleceń po określonym opóźnieniu lub wykonywanie okresowe.

Przyjrzyjmy się, jak ScheduledThreadPool działa na przykładzie.

Na przykład mamy zadanie sprawdzania poczty co 5 sekund, przy czym sprawdzanie to nie powinno wpływać na działanie programu głównego i wiąże się z ewentualnym dodatkowym zużyciem zasobów.

Mamy klasę zadań, która modeluje sprawdzanie poczty.


public class Task implements Runnable {
   @Override
   public void run() {
       System.out.println("Checking email...");
   }
}

Następnie tworzymy pulę wątków i planujemy uruchomienie sprawdzania.


ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
executorService.scheduleAtFixedRate(new Task(), 0, 5, TimeUnit.SECONDS);

Na wyjściu widzimy co 5 sekund:

Sprawdzanie poczty...

Generalnie taką pulę możemy wykorzystać, jak w przykładzie, do wykonywania okresowych zadań „serwisowych”. Zadaniami serwisowymi nazywamy te zadania, które muszą być wykonane niezależnie od działania głównej funkcjonalności programu.