JVM이 최소한 신호 및 .NET Framework 애플리케이션에 의해 생성 된 모든 실행중인 스레드를 정상적으로 인터럽트 ( thread.interrupt()
) 할 것으로 예상합니다 .SIGINT (kill -2)
SIGTERM (kill -15)
이런 식으로 신호가 그들에게 전달되어 표준 방식으로 정상적으로 스레드 취소 및 리소스 종료가 가능합니다 .
그러나 이것은 사실이 아닙니다 (적어도 내 JVM 구현에서는 Java(TM) SE Runtime Environment (build 1.8.0_25-b17), Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
.
다른 사용자가 언급했듯이 종료 후크 의 사용은 필수로 보입니다.
그래서 어떻게 처리할까요?
우선, 모든 프로그램에서 신경 쓰지 않고 사용자 취소 및 예상치 못한 종료를 추적하려는 경우에만 해당됩니다. 예를 들어, Java 프로그램이 다른 사람이 관리하는 프로세스라고 가정 해보십시오. 정상적으로 종료되었는지 ( SIGTERM
관리자 프로세스에서) 또는 종료가 발생했는지 (시작시 작업을 자동으로 다시 시작하기 위해) 구별 할 수 있습니다 .
기본적으로 나는 항상 장기 실행 스레드가 주기적으로 중단 된 상태를 인식하고 중단 된 InterruptedException
경우 던집니다 . 이를 통해 개발자가 제어하는 방식으로 실행을 완료 할 수 있습니다 (또한 표준 차단 작업과 동일한 결과를 생성 함). 그런 다음 스레드 스택의 최상위 수준에서 InterruptedException
캡처되고 적절한 정리가 수행됩니다. 이러한 스레드는 인터럽트 요청에 응답하는 방법을 알고 있도록 코딩되었습니다. 높은 응집력 디자인.
따라서 이러한 경우에는 JVM이 기본적으로 수행해야한다고 생각하는 작업을 수행하는 종료 후크를 추가합니다. 아직 실행중인 내 애플리케이션에서 생성 된 모든 비 데몬 스레드를 중단합니다.
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("Interrupting threads");
Set<Thread> runningThreads = Thread.getAllStackTraces().keySet();
for (Thread th : runningThreads) {
if (th != Thread.currentThread()
&& !th.isDaemon()
&& th.getClass().getName().startsWith("org.brutusin")) {
System.out.println("Interrupting '" + th.getClass() + "' termination");
th.interrupt();
}
}
for (Thread th : runningThreads) {
try {
if (th != Thread.currentThread()
&& !th.isDaemon()
&& th.isInterrupted()) {
System.out.println("Waiting '" + th.getName() + "' termination");
th.join();
}
} catch (InterruptedException ex) {
System.out.println("Shutdown interrupted");
}
}
System.out.println("Shutdown finished");
}
});
github에서 테스트 신청 완료 : https://github.com/idelvall/kill-test
kill -9
나에게 의미 : "자신, 파울 프로세스, 너와 떨어져!", 프로세스는 중단 될 것입니다. 바로.