stop 메서드로 쓰레드를 강제 종료하면 위험하다고 했습니다. 그러면 어떻게 종료하면 좋을까요? 몇 가지 방법이 있는데요. 그 중 하나는 Interrupt 메소드를 쓰는 것입니다.

 

 


 worker Thread가 vector에 수를 넣는 연산을 한다고 해 봅시다.

 

 

 그런데, 중간에 sleep을 넣어놓았습니다. 이 때 worker Thread에 Interrupt를 걸면 어떻게 동작하는지 봅시다.

 

 

 Main이 단위시간 1동안 sleep를 하고, Int를 출력합니다. 그리고 w1에 Interrupt를 보내는데요. 공식 문서에 나온 이 함수의 설명을 빌리면, 아래와 같습니다.

 

 여기서 중요한 키워드를 뽑아보면, blocked, 인터럽트 status, receive, 인터럽트 예외 정도가 있습니다. wait나 join, sleep 등의 메소드 등으로 block이 되었을 때, 인터럽트 상태가 클리어 되고, 예외를 수신 받는데요. 19번째 줄에 Thread의 sleep 메서드를 호출하고 있습니다.

 

 

 그러면, 이런 식으로 실행이 될 수 있을 겁니다. 중요한 것은 w1.join()은, w1이 끝날 때 까지 block 시키는 함수라는 것입니다. 그것이 호출되기 전이였기 때문에, worker Thread가 v.add, sleep를 하는 도중에 Main thread가 w1에게 인터럽트를 걸 수 있다는 의미입니다.

 

 이 메서드를 호출하면, 인터럽트 state가 켜지는데요.

 

 

 이 때, w1이 sleep(1)을 호출하면, w1이 blocked가 됩니다. 이 때, 인터럽트 상태가 1이기 때문에, w1은 예외를 받게 됩니다.

 

 

 그러면, 23번째 catch 절에 걸려서, catch block을 수행할 겁니다. Worker의 run 메소드를 조금 수정해 보겠습니다. add 메서드가 수행되고 난 후에, 추가된 수를 출력하게끔 해 볼 겁니다.

 

 

 1줄만 추가되었군요. w1 Thread가 다음의 run 함수를 수행할 때, 실행 결과는 어떻게 나올까요? 사실, w1 Thread와 Main Thread가 어떻게 실행될지는 모릅니다. 그러니, 당연하게도 실행 결과가 다르게 나올 수 있는데요.

 

 

이 때에는 0, 1이 print가 된 다음에, Main에서 w1에게 인터럽트를 걸어버렸습니다.

 

 

 0이 print 되고, sleep이 된 후에 Main에서 걸었을 수도 있습니다. w1이 어디까지 수행하고 Main에 의해서 걸리는지는 모릅니다. 하지만, status가 켜지고, w1이 sleep을 호출한 경우에, 인터럽트 예외를 수신한 것은 동일하다는 것을 알 수 있어요. 그러면, catch 절에서 적절하게 처리를 해 주면 되겠네요.

 

 


 그런데, 이 status가 켜졌는지 검사하는 방법도 있을 거에요. interrupted를 호출하거나, isInterrupted를 호출하면, 그 status가 켜졌는지 검사합니다.

 

 

 이 둘은 차이점이 있는데요. Thread.interrupted를 호출하면, 호출한 후에, status가 clear 됩니다. 2번 이상 호출하면 false를 리턴한다는 이야기입니다. 그리고, 메서드 부분이 기울임체로 되어 있는데요. 정적 메소드입니다.

 

 

 isInterrupted는, 호출이 된 후에도 status가 clear 되지 않습니다. 그리고 정적 메서드가 아님을 알 수 있어요. 여기서 문제. 해당 Thread가 인터럽트가 걸려서, 예외를 수신받았습니다. 그 후에, 이 둘을 호출하면 어떤 값을 리턴할까요?

 

 

 만약에 예외를 수신 받는다면, status를 초기화 한다는 문구가 기억나실 겁니다. 이것을 간파하셨다면, catch가 되고 난 후에, 둘 다 거짓이라는 값이 리턴될 거라는 예상을 할 수 있습니다.

 

 

 false 2개가 찍힌 것을 확인할 수 있어요. 쭉 보셨다면, OS의 인터럽트와는 다른 개념이라는 것을 눈치 채셨을텐데요. 이 둘이 어떻게 다른지 찾아보시는 것도 재미있는 공부가 되지 않을까 싶습니다.