자바

JAVA 자바 Thread 자바 스레드 : 스레드의 안전한 종료 stop플래그, interrupt()

알통몬_ 2017. 3. 15. 11:15
반응형


안녕하세요 알통몬입니다.

공감 및 댓글은 포스팅 하는데 아주아주 큰 힘이 됩니다!!

포스팅 내용이 찾아주신 분들께 도움이 되길 바라며

더 깔끔하고 좋은 포스팅을 만들어 나가겠습니다^^

 



스레드의 안전한 종료 stop플래그, interrupt()

 스레드는 자신의 run() 메서드가 모두 실행되면 자동적으로 종료됩니다.

경우에 따라 실행 중인 스레드를 즉시 종료할 필요가 생길 수 있습니다. 

예를 들면 동영상을 끝까지 보지 않고 사용자가 멈춤을 요구할 경우가  있을 수 있습니다. 

Thread는 스레드를 즉시 종료시키기 위해 stop()메서드를 제공하지만 

이 메서드는 Deprecated되어있습니다. 

 =>아래 두가지 방법은 스레드를 즉시 종료시키기 위한 최선의 방법입니다.


stop 플래그를 이용하는 방법

 스레드는 run() 메서드가 끝나면 자동적으로 종료되기 때문에 run() 메서드가 

정상적으로 종료되도록 유도하는 것이 최선입니다. 

아래 코드는 stop  플래그를 이용해 run() 메서드의 종료를 유도합니다.

public class XXXThread extends Thread {

     private boolean stop; // stop 플래그 필드

     

     public void run() {

        while(!stop){ stop가 true가 되면 run() 종료

           스레드가 반복 실행하는 코드;

        }

       //스레드가 사용한 자원 정리

   }

}


예제를 보겠습니다.

실행 클래스

public class StopFlagExample {

public static void main(String[] args)  {

PrintThread1 printThread = new PrintThread1();

printThread.start();

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

}

printThread.setStop(true);

}

}


무한 반복해서 출력하는 스레드

public class PrintThread1 extends Thread {

private boolean stop;

public void setStop(boolean stop) {

  this.stop = stop;

}

public void run() {

while(!stop) {

System.out.println("실행 중");

}

System.out.println("자원 정리");

System.out.println("실행 종료");

}

}

 




interrupt() 메서드를 이용하는 방법

 스레드가 일시 정지 상태에 있을 때 InterruptedException 예외를 발생시키는 역할을 합니다. 

이것을 이용해 run() 메서드를 정상 종료 시킬 수 있습니다. 

예를 들어 ThreadA가 ThreadB를 생성해서 start() 메서드로 ThreadB를 실행했다고 하면,


예제)

실행 클래스

public class InterruptExample {

public static void main(String[] args)  {

Thread thread = new PrintThread2();

thread.start();

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

}

thread.interrupt();

}

 

}


무한 반복해서 출력하는 스레드

public class PrintThread2 extends Thread {

public void run() {

//how1

try {

while(true) {

System.out.println("실행 중");

Thread.sleep(1);

}

} catch(InterruptedException e) {

}

System.out.println("자원 정리");

System.out.println("실행 종료");

}

} 실행 결과는 위 예제와 같습니다.


* 스레드가 실행 대기 또는 실행 상태에 있을 때 interrupt() 메서드가 실행되면 

즉시 InterruptedException 예외가 발생하지 않고, 스레드가 미래에 일시 정지 상태가 되면 

InterruptedException 발생합니다. 

 =>스레드가 일시 정지 상태가 되지 않으면 interrupt() 메서드 호출은 아무런 의미가 없습니다. 

그래서 짧은 시간이나마 일시정지시키기 위해 Thread.sleep(1)을 사용한 것입니다. 

일시 정지를 만들지 않고도 interrupt() 호출 여부를 알 수 있는 방법도 있습니다. 

interrupt() 메서드가 호출되었다면 

스레드의 interrupted() 와 isInterrupted() 메서드는 true를 리턴합니다.

interrupted() 는 static 메서드로 현재 스레드가 interrupted 되었는지 확인하고

isInterrupted() 메서드는 인스턴스 메서드로 현지 스레드가 interrupted()되었는지 확인할 때 

사용합니다. 둘 중 아무거나 사용해도 됩니다.

아래 예제는 PrinThread2의 Thread.sleep(1) 대신 Thread.interrupted() 사용한 것입니다.

public class PrintThread2 extends Thread {

public void run() {

while(true) {

System.out.println("실행 중");

if(Thread.interrupted()) {

break;

}

}

System.out.println("자원 정리");

System.out.println("실행 종료");

}

}

반응형