shutdown()
только заставит ExecutorService
не принимать больше задач, но продолжит выполнение всех ожидающих задач до конца.Поскольку вы на самом деле хотите прекратить выполнение задач, вы должны в первую очередь использовать shutdownNow()
, который будет посылать сигнал прерывания.
public static void main(final String... args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
executorService.shutdownNow();
try {
executorService.awaitTermination(
SHUTDOWN_TIMEOUT.getSeconds(),TimeUnit.SECONDS);
} catch (InterruptedException e) {}
}));
for (int i = 0; i < 2; i++) {
executorService.execute(create());
}
}
private static Runnable create() {
return () -> {
while(!Thread.interrupted()) {
try {
Thread.sleep(5000);
System.out.println("Hatella" + Thread.currentThread().getName());
}
catch(InterruptedException ex) {
break;
}
catch (Throwable t) {
}
}
System.out.println("thread exit " + Thread.currentThread().getName());
};
}
Флаг прерывания можно запрашивать не только через Thread.interrupted()
, онтакже сделает блокирующие действия, такие как Thread.sleep(…)
, прекращением ранее, сообщая о ситуации через InterruptedException
.В обоих случаях, когда Thread.interrupted()
вернул true
или когда был выдан InterruptedException
, статус прерывания будет сброшен, поэтому важно либо немедленно отреагировать на него, либо помнить, что вы его получили.Таким образом, в приведенном выше примере catch(InterruptedException ex)
содержит break
для завершения цикла.
Но, как показано, прерывание не прерывает поток, а позволяет реагировать на него, например, путем очистки при необходимости,перед выходом.
Обратите внимание, что, когда единственными длительными операциями являются блокирующие, вам вообще не нужно опрашивать статус прерывания вручную, например, будет работать также следующее:
private static Runnable create() {
return () -> {
while(true) {
try {
Thread.sleep(5000);
System.out.println("Hatella" + Thread.currentThread().getName());
}
catch(InterruptedException ex) {
System.out.println("got "+ex+", "+Thread.interrupted());
break;
}
catch (Throwable t) {
}
}
System.out.println("thread exit");
};
}
Поскольку этот код не проверяет и не сбрасывает прерванное состояние с помощью Thread.interrupted()
, сигнал будет сохраняться до следующего вызова Thread.sleep
, что будет достаточно скоро, чтобы появиться в качестве немедленного ответа, поскольку код выполняется между двумяsleep
звонки короткие.