class Dummy { public synchronized void todo() { try { System.out.println("start...."); wait(); }catch(InterruptedException e) { System.out.println("interrupted"); System.out.println("t1(run) :" + Thread.currentThread().isInterrupted()); } } } public class InterruptEx { public static void main(String[] args) { final Dummy d = new Dummy(); Thread t1 = new Thread() { @Override public void run() { d.todo(); System.out.println("i'm dead"); } }; t1.start(); t1.interrupt(); //호출되면 스레드는 실행불가상태에서 대기열로 돌아온다. } } //결과 start.... interrupted t1(run) :false i'm dead
interrupt()되면, 스레드는 실행불가상태(not runnable)에서 대기열(runnable)로 돌아온다.
실행불가상태가 중단이 된다. 실행불가를 실행가능한 상태로 돌려준다.
실행불가상태가 아니면 아무일도 안 일어난다.
그런데, 실행불가상태(not runnable)로 빠져있는 스레드가 대기열(runnable)로 들어와서(깨어난 후에) 다시 run상태로 가면 예외처리된 것으로 처리한다.
예외가 되었다고 생각되고, catch문에 있는 내용이 출력된다.
코드설명
main창에서 t.start()해주고, t.interrupt()까지 해줘서 t스레드가 탈출권을 가지게 된다. 그래서 not runnable에서 바로 나오고, 다시 runnable-> run으로 가게 되는데 그럼 탈출권을 쓰고 나왔기 때문에 예외가 발생해서 catch문안에 값이 출력되게 된다.
결과 창을 보면, t1(run) :false
wait() 걸리기 전이면 true가 나온다. 실행불가 상태엿다가 다시 깨어나면 정보가 초기화가 된다. interrupted를 받았다는 정보를 없애고 false로 바꾼다.
미리 interrupt(무인도탈출권)를 받으면은 실행하는 도중에 실행불가 상태로 빠지면, 미리 받았기 때문에 실행불가에 안 갇혀있고 대기열로 돌아온다.
내가 선택한 놈을 깨울 수 있는데, 그 타이밍을 맞출 수 있을 것인가가 고민이다.
동작하는 순번 등이 계속 바뀌고, 내가 의도한 것은 갇혀있기를 원했는데, 타이밍이 안맞으면 걔가 안갇힐 수 있다. 예측이 안된다.
되게 조심해서 써야한다. 100프로 갇힌다고 생각했을 때 골라서 인터럽트 사용할 수 있다.
인터럽트 막 사용하지 않기.
public class InterruptEx1 { public static void main(String[] args) { Thread t1 = new Thread() { @Override public void run() { try { System.out.println("isInterrupted:" + isInterrupted()); System.out.println("sleep..."); //1분간 잠든다.. run -> not runnable Thread.sleep(1000*6); }catch(InterruptedException e) { //interrupedException 처리되는 순간 //interrupt받은 기록이 사라진다. System.out.println("wake up"); System.out.println("isInterruped:" + isInterrupted()); } for(int i = 0 ; i<10 ; i++) { System.out.println(i); } } }; t1.start(); //t1.state : not runnable -> runnable 🌜try { Thread.sleep(5000); }catch (Exception e) {}🌛 t1.interrupt(); } } //결과 isInterruped:true 여기서는 true sleep... wake up isInterruped:false 여기는 false 0 1 2 3 4 5 6 7 8 9
원래는 재울려고 이 코드를 만들어 놨는데, 애가 깸. 1분동안 잠들지 않고 바로 일어남. - 나의 생각과 다르게 코드가 작동.
코드설명
main이 먼저 생성되었으니까 run에 가서 실행한다. start()시켜서 t1스레드를 runnable상태로 만든다. 그리고 try문을 만나서 잠든다. 그 사이 t1이 run상태가 되어서 run()메서드를 읽는다. 그리고 잠든다. 그리고 main이 일어나서 interrupt()를 해주고, 그리고 main은 죽는다. 그리고 t1은 살아나서 run()으로 가지만 interrupt로 일어나서 예외가 발생한다. 그래서 wakeup하고 이미 탈출권을 썼으니까 false로 나온다.
🌜 부분의 코드(try-catch)를 작성하면 main이 잠깐 잠든 사이에 t1이 run 상태로 가게 된다. 그러면 interrupted되지 않았으니까 false로 나온다. 이렇게 짜는 게 쉽지 않다.
먜 ) t1.start()랑 t1.interrupt()는 main이 다 하는 거다.
public class InterruptTest { public static void main(String[] args) { Thread t = new Thread() { public void run() { try { System.out.println("try - isInterrupted : " + isInterrupted()); ` //인터럽트 받은 기록이 초기화됨(false) 🌜System.out.println( "try - interrupted : " + Thread.interrupted() ); // true가 나옴. 🌛 ` System.out.println("ok"); Thread.sleep(4000); }catch(InterruptedException e){ System.out.println( "catch - isInterrupted :" + isInterrupted()); } } }; t.start(); t.interrupt(); System.out.println( "isInterrupted :" + t.isInterrupted()); try { Thread.sleep(1000); }catch(Exception e) {} System.out.println("isInterrupted : " + t.isInterrupted()); } } //결과 isInterrupted :true try - isInterrupted : true try - isInterrupted : true ok isInterrupted : false
🌜🌛 이부분 보면, true가 나온다. catch안의 구문이 안나옴. static메소드.
이거는 수행한 스레드(t1)가 수행하게 되면, 인터럽트를 받았는지 안받았는지 알려주고, 만약에 인터럽트를 받았으면 true를 리턴하고 인터럽트 받았던 기록을 없애버린다. 4초 잠들었다가 catch문 걍 넘어간다.
수행한 t1이 초기화되는 거.
💡팁) println안에 명령어를 넣어도 명령입력이 된 것으로 작동을 하긴 한다.
public class InterruptEx2 { public static void main(String[] args) { Thread t1 = new Thread() { @Override public void run() { long count = 0; while(!isInterrupted()) { //어떤 스레드가 멈추는 게 가능하다. //뭔가 한다. //반복문 안에서 해야할 일들이 엄청 오래 걸리는 게 있을 수 있다. -> 인터럽트 날려도 구문의 특성 상 while문 안이 다 동작해야지 조건문이 된다. count++; } System.out.println("interrupted -> count = " + count); System.out.println("isInterrupted :" + isInterrupted()); //...wait,sleep,join... } }; t1.start(); try { Thread.sleep(1000); }catch(Exception e) { } t1.interrupt(); t1.isInterrupted(); } } //interrupted -> count = 2056881689 //isInterrupted :true이부분 잘 모르겠음.
03.16수업