Java ExecutorService to interfejs, który umożliwia asynchroniczne wykonywanie zadań w wątkach. Interfejs Java ExecutorService znajduje się w pakiecie java.util.concurrent. ExecutorService pomaga w utrzymaniu puli wątków i przydziela im zadania. Zapewnia także możliwość ustawiania zadań w kolejce do momentu udostępnienia wolnego wątku, jeśli liczba zadań przekracza liczbę dostępnych wątków.
Metody Java ExecutorService
metoda | Opis |
---|---|
wartość logiczna WaitTermination(długi limit czasu, jednostka TimeUnit) | Ta metoda blokuje zadanie wejścia do ExecutorService do czasu zakończenia wszystkich zadań po żądaniu zamknięcia, upłynięcia określonego limitu czasu lub przerwania bieżącego wątku, w zależności od tego, co nastąpi wcześniej. |
Lista | Metoda ta wykonuje listę podanych zadań i zwraca listę kontraktów futures, które zawierają wyniki wszystkich zadań po ich wykonaniu. |
Lista | Metoda ta wykonuje podaną listę zadań i zwraca listę kontraktów futures, które zawierają wyniki wszystkich zadań po ich ukończeniu lub upływie limitu czasu, w zależności od tego, co nastąpi wcześniej. |
T invokeAny(Collection extends Callable>zadania) | Metoda ta wykonuje podaną listę zadań i zwraca wynik jednego zadania, które zostaje ukończone bez zgłaszania wyjątku. |
T invokeAny(Collection extends Callable>zadania, długi limit czasu, jednostka TimeUnit) | Metoda ta wykonuje podaną listę zadań i zwraca wynik jednego zadania, które zostaje ukończone bez zgłaszania wyjątku przed upływem limitu czasu. |
wartość logiczna isShutdown() | Ta metoda zwraca informację, czy dany executor został zamknięty, czy nie. |
wartość logiczna isTerminate() | Ta metoda zwraca wartość true, jeśli wszystkie zadania zostały wykonane po zamknięciu. |
unieważnienie zamknięcia() | Metoda ta pozwala na dokończenie zadań wcześniej przesłanych do ExecutorService i nie pozwala na przyjęcie innych zadań. |
Lista zamykana teraz() | Ta metoda zatrzymuje wszystkie aktywnie wykonywane zadania, zatrzymuje wykonywanie zadań umieszczonych w kolejce i zwraca listę zadań umieszczonych w kolejce. |
Przyszłe przesłanie (zadanie możliwe do wywołania) | Ta metoda przesyła zadanie zwracające wartość do wykonania i zwraca przyszłość, która reprezentuje oczekujący wynik zadania. |
Przyszłe przesłanie (zadanie możliwe do wykonania) | Ta metoda przesyła zadanie do wykonania i zwraca wartość Future reprezentującą to zadanie. Zwraca wartość null po pomyślnym zakończeniu. |
Przyszłe przesłanie (zadanie możliwe do wykonania, wynik T) | Ta metoda przesyła zadanie do wykonania i zwraca wartość Future reprezentującą to zadanie. |
Prosty program Java ExecutorService
public class ExecutorServiceExample { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(10); executorService.execute(new Runnable() { @Override public void run() { System.out.println('ExecutorService'); } }); executorService.shutdown(); } }
Wyjście:
W tym programie tworzymy usługę ExecutorService z dziesięcioma wątkami i przypisujemy jej anonimową, uruchamialną implementację, która wykonuje zadanie wydrukowania usługi ExecutorService, a po zakończeniu tego zadania zamykamy usługę executora.
Jak korzystać z usługi Java ExecutorService
Tworzenie instancji usługi ExecutorService
Możemy użyć Java ExecutorService do utworzenia pojedynczego wątku, puli wątków lub zaplanowanej puli wątków. Klasa Executors udostępnia metody fabryczne umożliwiające utworzenie instancji ExecutorService w następujący sposób:
ExecutorService executorService1 = Executors.newSingleThreadExecutor(); //Creates //a ExecutorService object having a single thread. ExecutorService executorService2 = Executors.newFixedThreadPool(10); // Creates a //ExecutorService object having a pool of 10 threads. ExecutorService executorService3 = Executors.newScheduledThreadPool(10); //Creates a scheduled thread pool executor with 10 threads. In scheduled thread //pool, we can schedule tasks of the threads.
Przypisywanie zadań do ExecutorServices
Aby przypisać zadanie do ExecutorService, możemy skorzystać z następujących metod:
- wykonaj (zadanie możliwe do uruchomienia)
- przesłać (zadanie możliwe do wykonania) / przesłać (zadanie możliwe do wywołania)
- invokeAny(Kolekcja extends Callable>zadania)
- invokeAll (kolekcja extends Callable>zadania)
Przykład przypisania zadania do ExecutorService przy pomocy metody generate().
Metoda ExecutorService Java ExecutorService pobiera uruchamialny obiekt i wykonuje swoje zadanie asynchronicznie. Po wywołaniu metody wykonywania wywołujemy metodę zamykania, która blokuje umieszczenie w kolejce wszelkich innych zadań w usłudze executorService.
public class ExecutorServiceExample { public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.execute(new Runnable() { @Override public void run() { System.out.println('ExecutorService'); } }); executorService.shutdown(); } }
Wyjście:
ExecutorService
Przykład przypisania zadania do ExecutorService za pomocą metody Submit()
Metoda Submit() pobiera obiekt możliwy do uruchomienia i zwraca obiekt Future. Obiekt ten jest później używany do sprawdzania statusu Runnable, czy zakończył on wykonywanie, czy nie.
public class ExecutorServiceExample { public static void main(String[] args) { ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.submit(new Runnable() { @Override public void run() { System.out.println('ExecutorService'); } }); } }
Przykład przypisania zadania do ExecutorService metodą invokeAny().
Metoda invokeAny() pobiera kolekcję obiektów Callablle lub obiektów klas implementujących Callable. Ta metoda zwraca przyszły obiekt wywoływalnego obiektu, który zostanie pomyślnie wykonany jako pierwszy.
znowu skorupa Bourne’a
public class ExecutorServiceExample { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService executorService = Executors.newSingleThreadExecutor(); Set<callable> callables = new HashSet<callable>(); callables.add(new Callable() { public String call() throws Exception { return 'Task 1'; } }); callables.add(new Callable() { public String call() throws Exception { return 'Task 2'; } }); callables.add(new Callable() { public String call() throws Exception { return 'Task 3'; } }); String result = executorService.invokeAny(callables); System.out.println('result = ' + result); executorService.shutdown(); } } </callable></callable>
Wyjście:
result = Task 1
Wynik przechowuje zadanie 1, ponieważ pierwszy możliwy do wywołania obiekt został pomyślnie wykonany jako pierwszy.
Przykład przypisania zadania do ExecutorService metodą invokeAll().
Metoda invokeAll() pobiera kolekcję obiektów Callable zawierających zadania i zwraca listę obiektów Future zawierających wyniki wszystkich zadań.
public class ExecutorServiceExample { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService executorService = Executors.newSingleThreadExecutor(); Set<callable> callables = new HashSet<callable>(); callables.add(new Callable() { public String call() throws Exception { return 'Task 1'; } }); callables.add(new Callable() { public String call() throws Exception { return 'Task 2'; } }); callables.add(new Callable() { public String call() throws Exception { return 'Task 3'; } }); java.util.List<future> futures = executorService.invokeAll(callables); for(Future future : futures){ System.out.println('future.get = ' + future.get()); } executorService.shutdown(); } } </future></callable></callable>
Wyjście:
future.get = Task 1 future.get = Task 3 future.get = Task 2
Jak zamknąć usługę ExecutorService
Kiedy już skończymy zadania powierzone ExecutorService, musimy je zamknąć, ponieważ ExecutorService wykonuje zadanie w różnych wątkach. Jeśli nie zamkniemy usługi ExecutorService, wątki będą nadal działać, a maszyna JVM nie zostanie zamknięta.
Proces zamykania można wykonać trzema następującymi metodami:
- metoda zamknięcia().
- metoda ShutdownNow().
- metoda waitTermination().