Ilekroć dzwonię pod numer shutdownNow()
lub shutdown()
, nie wyłącza się. Czytałem o kilku wątkach, w których mówiło się, że wyłączanie nie jest gwarantowane - czy ktoś może mi zapewnić dobry sposób robienia tego?Jak zamknąć ExecutorService?
Odpowiedz
Typowy wzór jest:
executorService.shutdownNow();
executorService.awaitTermination();
Dzwoniąc shutdownNow
, wykonawca będzie (ogólnie) starają się przerwać nici, którymi zarządza. Aby zamknięcie było pełne wdzięku, musisz przechwycić przerwany wyjątek w wątkach lub sprawdzić stan przerwania. Jeśli nie, twoje wątki będą działać wiecznie, a twój executor nigdy nie będzie w stanie się zamknąć. Dzieje się tak dlatego, że przerwanie wątków w Javie jest procesem opartym na współpracy (tzn. Kod przerywany musi coś zrobić, gdy zostanie poproszony o zatrzymanie, a nie kod przerywający kod).
Na przykład poniższy kod drukuje Exiting normally...
. Ale jeśli skomentujesz linię if (Thread.currentThread().isInterrupted()) break;
, wydrukuje ona Still waiting...
, ponieważ wątki w executorze nadal działają.
public static void main(String args[]) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(new Runnable() {
@Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) break;
}
}
});
executor.shutdownNow();
if (!executor.awaitTermination(100, TimeUnit.MICROSECONDS)) {
System.out.println("Still waiting...");
System.exit(0);
}
System.out.println("Exiting normally...");
}
Alternatywnie, może to być napisane z InterruptedException
tak:
public static void main(String args[]) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(new Runnable() {
@Override
public void run() {
try {
while (true) {Thread.sleep(10);}
} catch (InterruptedException e) {
//ok let's get out of here
}
}
});
executor.shutdownNow();
if (!executor.awaitTermination(100, TimeUnit.MICROSECONDS)) {
System.out.println("Still waiting...");
System.exit(0);
}
System.out.println("Exiting normally...");
}
wiesz, jeśli zamknięcie inicjuje również 'Thread.interrupt()', z Java API nie robi wydaje się, że 'shutdown' przerywa wątki? – Bionix1441
@ Bionix1441 Nie, nie ma. 'shutdownNow' działa jednak. – assylias
Najlepszym sposobem jest to, co faktycznie mają w javadoc, która jest:
Poniższe zamykają metoda w dół ExecutorService w dwóch fazach, najpierw przez wywołanie
shutdown
, aby odrzucić przychodzące zadania, a następnie wywołanieshutdownNow
, jeśli to konieczne, aby anulować jakiekolwiek długotrwałe zadania:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
Proszę zaznaczyć właściwą odpowiedź jako zaakceptowany – gonephishing