[Java Thread] 쓰레드 종료, 안전하게 종료하는 방법

기존에는 stop() 메소드를 활용해서 현재 진행중인 스레드를 종료시켰었나봅니다.

 

하지만 해당 메소드가 Deprecated 되어 있습니다.

 

왜 그럴까 생각해보았을땐 대충 공유객체에 대한 자원관리와 갑작스런 스레드 종료에 따른 어플리케이션 불안 정도를 꼽을 수 있었는데요.

 

Thread 클래스에 존재하는 stop 메소드의 주석을 우선 뜯어보았습니다.

 

Thread 클래스의 stop 메소드 deprecated 관련 주석 내용

 

메소드는 본질적으로 안전하지 않습니다. Thread stop 메소드로 스레드를 종료하는 것은 스레드가 가진 모든 자원이 해제됩니다. 예를 들어, 공유객체입니다. 공유객체를 특정 스레드가 점유하여 처리하고 있을 때, 갑작스럽게 종료하게 된다면 해당 공유객체는 미완료처리된 불완전 객체로써 메모리에 남게됩니다. 그로인해 시스템은 의도하지 않은 행동을 취할 수 있습니다. stop의 사용은 대상 스레드가 실행을 중지해야 함을 나타내도록 일부 변수를 수정하는 코드로 대체되어야 할 것 입니다. 대상 스레드는 이 변수에 대해서 정기적으로 확인하고 변수가 실행중지를 나타내는 경우 순서대로 실행메소드에서 반환해야합니다. 대상 스레드가 (예를들어 조건변수 같은) 오랜기간동안 대기하는 경우 interrupt 메소드를 활용하여 대기를 중단해야합니다.

약간의 의역과 해석을 해보니 본질적으로 불완전한 메소드이기 때문에 아예 deprecated처리를 했네요...!!

 

대안에 관한 힌트로 interrupt를 제시하고 있는데, 직접적으로 제시하는 것 보다는 좀더 간접적으로 표현한 것 같습니다.

 

이제 이를 java 코드로 간단히 예제를 구성하여 짜보겠습니다.

 


 

스레드를 안전하게 종료시킬 수 있는 방법 예제
public static void main(String[] args) throws InterruptedException {

    Thread thread = new Thread(() -> {
        try {
            while (!Thread.currentThread().isInterrupted()) {
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
    thread.start();

    System.out.println(Thread.currentThread().getName());
    Thread.sleep(2000);
    thread.interrupt();
}

일정한 반복작업을 하는 스레드의 경우 while문에 조건식으로 isInterrupted() 메소드를 활용하여 처리할 수 있습니다.

 

예제의 경우 1초간격으로 현재 스레드의 이름을 출력하고 interrupt() 메소드에 의해 스레드가 중단될 경우 자연스럽게 해당 스레드가 종료될 수 있도록 유도합니다.

 

여기서 좀더 발전하여 공유객체 및 기타 자원을 활용한다면..

 

public static void main(String[] args) throws InterruptedException {

    Thread thread = new Thread(() -> {
    	// 자원 선언
    
        try {
            while (!Thread.currentThread().isInterrupted()) {
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
        	// 공유자원 정리
            // 해당 스레드에서 사용한 메모리 자원 정리(close 같은 작업들)
        }	
    });
    thread.start();

    System.out.println(Thread.currentThread().getName());
    Thread.sleep(2000);
    thread.interrupt();
}

주석으로 다음과 같이 처리할 자원이 있으면 종료해주어 스레드에 대한 안전한 방법(thread-safe)으로 하나의 스레드를 종료처리할 수 있습니다.

댓글

Designed by JB FACTORY