안녕하세요. 점냥입니다:)
이번 포스팅에서는 Java Thread를 외부에서 종료시키는 방법에 대해서 작성해보려고 합니다.
이 주제는 최근 기업 기술 질문에서 대답을 못한 질문 중에 하나로 정답을 찾고 정리하고자 이번 포스팅을 준비하게 되었습니다.
while문에서 무한 루프를 돌고 있어 종료되지 않는 스레드, 외부에서 어떻게 강제 종료시킬 수 있는가?
class SampleThread implements Runnable {
@Override
public void run() {
while(true) {
System.out.println("thread is running");
}
}
}
모든 Thread는 Runnable의 run() 함수 내 코드를 실행하고 함수의 모든 코드가 실행이 되면 스레드는 자동으로 종료됩니다. 하지만 위 코드에서처럼 반복문의 종료 조건이 명시되지 않고 무한적으로 실행이 된다면 외부에서 종료하지 않는 이상 스레드는 종료되지 않습니다.
Thread.destory()?, Thread.stop() 함수 사용하기?
Thread.destory()
함수는 Thread를 파괴하기 위해 함수가 만들어졌지만, 이 함수를 구현하면 리소스를 정리하지 못해 데드락이 발생할 수 있다는 단점이 생겨서 구현이 되어 있지 않다고 합니다. 리소스를 정리하면서 종료시키면 안 되나..?라는 의문점이 들지만 여하튼 오라클에서는 그렇게 할 수 없다고 하네요.
/**
* Throws {@link NoSuchMethodError}.
*
* @deprecated This method was originally designed to destroy this
* thread without any cleanup. Any monitors it held would have
* remained locked. However, the method was never implemented.
* If if were to be implemented, it would be deadlock-prone in
* much the manner of {@link #suspend}. If the target thread held
* a lock protecting a critical system resource when it was
* destroyed, no thread could ever access this resource again.
* If another thread ever attempted to lock this resource, deadlock
* would result. Such deadlocks typically manifest themselves as
* "frozen" processes. For more information, see
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">
* Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
* @throws NoSuchMethodError always
*/
@Deprecated
public void destroy() {
throw new NoSuchMethodError();
}
Thread.stop()
함수는 어떨까요? 이 함수도 마찬가지로 Deprecated 된
함수이고 그 이유에 대해서는 링크에서 설명하고 있습니다.
Java의 모든 객체들은 Monitor
를 가지고 있으며 하나의 객체를 여러 스레드에서 접근할 수 없도록 잠금 기능을 사용하여 중복 접근을 막는 역할을 수행합니다. 그런데 Thread.stop 함수를 사용해서 스레드가 멈추면 이 Monitor 잠금 기능이 풀리면서, 여러 쓰레드에서 접근이 가능하게 되는 문제가 생겨 일관성이 깨진다고 합니다.
Thread.interrupt() 함수 사용하기
스레드를 외부에서 안전하게 종료시키는 방법은 Thread.interrupt()
를 사용하는 것입니다.
Thread 객체는 interrupt라는 boolean 플래그 변수를 가지고 있고 이 함수를 호출하면 해당 플래그 값을
true
로 설정합니다. 주의할 점은 스레드를 즉시 종료시키는 방법은 아닙니다. interrupt 플래그 값이 true로 설정되고 스레드가 일시 정지상태가 되었을 때 (예를 들면 sleep() 함수를 호출했을 때) InterruptedException
오류를 발생시키게 되어 쓰레드가 종료되게 만들 수 있습니다.
public class ThreadKill {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new SampleThread());
thread.start();
Thread.sleep(10L);
thread.interrupt();
}
}
class SampleThread implements Runnable {
@Override
public void run() {
while(!Thread.interrupted()) {
System.out.println("thread is running");
}
}
or
@Override
public void run() {
try {
while(true) {
System.out.println("thread is running");
//Thread를 일시 정지상태로 만들어 interrupt 발생시키도록 유도
Thread.sleep(1L);
}
} catch (InterruptedException e) {
//자원 해제
}
}
}
참고
'Language > Java' 카테고리의 다른 글
Java의 Singleton (0) | 2020.06.01 |
---|---|
Java - String pool (0) | 2020.05.28 |