예를 들어서, 특정 스레드가 Thread.sleep() 을 통해 쉬고 있는데, 처리해야 하는 작업이 들어와서 해당 스레드를 급하게 깨워야 할 수 있다. 또는 sleep() 으로 쉬고 있는 스레드에게 더는 일이 없으니, 작업 종료를 지시할 수도 있다.
인터럽트를 사용하면, WAITING , TIMED_WAITING 같은 대기 상태의 스레드를 직접 깨워서, 작동하는 RUNNABLE 상태로 만들 수 있다.
public class ThreadStopMainV2 {
public static void main(String[] args) {
MyTask task = new MyTask();
Thread thread = new Thread(task, "work");
thread.start();
sleep(4000);
log("작업 중단 지시 thread.interrupt()");
thread.interrupt();
log("work 스레드 인터럽트 상태1 = " + thread.isInterrupted());
}
static class MyTask implements Runnable {
@Override
public void run() {
try {
while (true) {
log("작업 중");
Thread.sleep(3000);
}
} catch (InterruptedException e) {
log("work 스레드 인터럽트 상태2 = " +
Thread.currentThread().isInterrupted());
log("interrupt message=" + e.getMessage());
log("state=" + Thread.currentThread().getState());
}
log("자원 정리");
log("작업 종료");
}
}
}
위의 코드를 실행한 실행결과는 아래와 같다.
18:10:40.024 [ work] 작업 중
18:10:43.026 [ work] 작업 중
18:10:44.011 [ main] 작업 중단 지시 thread.interrupt()
18:10:44.021 [ main] work 스레드 인터럽트 상태1 = true
18:10:44.021 [ work] work 스레드 인터럽트 상태2 = false
18:10:44.022 [ work] interrupt message=sleep interrupted
18:10:44.022 [ work] state=RUNNABLE
18:10:44.022 [ work] 자원 정리
18:10:44.023 [ work] 작업 종료

main 스레드가 4초 뒤에 work 스레드에 interrupt() 를 건다. work 스레드는 인터럽트 상태( true )가 된다.
스레드가 인터럽트 상태일 때는, sleep() 처럼 InterruptedException 이 발생하는 메서드를 호출하거나 또는 이미 호출하고 대기 중이라면 InterruptedException 이 발생한다. (중요 🎈main 쓰레드가 interupt를 호출했다고 InterruptedException이 발생하는 것이 아니다!)
이때 2가지 일이 발생한다.
work 스레드는 TIMED_WAITING 상태에서 RUNNABLE 상태로 변경되고, InterruptedException 예외를 처리하면서 반복문을 탈출한다.
work 스레드는 인터럽트 상태가 되었고, 인터럽트 상태이기 때문에 인터럽트 예외가 발생한다.
인터럽트 상태에서 인터럽트 예외가 발생하면 work 스레드는 다시 작동하는 상태가 된다. 따라서 work 스레드의 인터럽트 상태는 종료된다.
work 스레드의 인터럽트 상태는 false 로 변경된다