wait()와 notify()
한 쓰레드가 객체에 lock을 걸고 어떤 조건이 만족될 때 까지 기다려야하는 경우, 이 쓰레드를 그대로 놔두면 이 객체를 사용하려는 다른 쓰레드들은 lock이 풀릴 때까지 같이 기다려야하는 상황이 발생합니다.
이러한 비효율을 개선하기 위해서 wait()와 notify()를 사용합니다. 한 쓰레드가 lock을 걸고 오래 기다리는 대신에 wait()를 호출하여 다른 쓰레드에게 제어권을 넘겨주고 대기상태로 기다리다가 다른 쓰레드에 의해서 notify()가 호출되면 다시 실행상태가 되도록하는 것을 말합니다.
wait()와 notify()의 특징
- wait()와 notify()는 Thread클래스가 아닌 Object클래스에 정의댄 메서드이므로 모든 객체에서 호출이 가능합니다.
- 쓰레드가 wait()를 호출하면 그 때까지 자신이 객체에 걸어 놓았던 lock을 풀고, wait()가 호출된 객체의 대기실(waiting pool)에서 기다립니다.
- notify()는 waiting pool에 있는 쓰레드 중에 하나만 깨우고 notifyAll()은 모든 객체를 깨웁니다.
- notify()로 호출할 경우 어떤 객체가 깨어날지 모르기때문에 notifyAll()로 모든 객체를 깨운 뒤에 JVM의 쓰레드 스케쥴링에 의해서 처리되는 것이 안전합니다.
- 동기화 블럭(synchronized블록)내에서만 사용할 수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // wait()와 notify() 예제 class Account{ int balance = 1000; public synchronized void withdraw(int money){ /* 잔고가 부족할 경우 wait()를 호출하여 lock을 풀고 waiting pool에 들어가면서 제어권을다른 쓰레드에게 양보하게 됩니다. */ while(balance < money){ try{ wait(); }catch(InterruptedException e){ } } balance -= money; } /* 다른 쓰레드에 의해서 deposit()메서드가 호출되어 잔고가 증가하면서 notify()를 호출하면 객체의 waiting pool에서 기다리고 있던 쓰레드를 깨우게 됩니다. */ public synchronized void deposit(int money){ balance += money; notify(); } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | // wait()와 notify() 예제2 class ThreadEx{ public static void main(String args[]){ MyThreadEx th1 = new MyThreadEx("*"); MyThreadEx th2 = new MyThreadEx("**"); MyThreadEx th3 = new MyThreadEx("***"); th1.start(); th2.start(); th3.start(); try{ Thread.sleep(2000); th1.suspend(); Thread.sleep(2000); th2.suspend(); Thread.sleep(3000); th1.resume(); Thread.sleep(3000); th1.stop(); th2.resume(); th2.stop Thread.sleep(3000); th3.stop(); }catch(InterruptedException e){ } } } } class MyThreadEx implements Runnable{ static final int RUNNING = 0; static final int SUSPENDED = 1; static final int STOPPED = 2; private int state = RUNNING; Thread th; MyThreadEx(String name){ th = new Thread(this, name); /// Thread(Runnable r, String name) } public void run(){ String name = Thread.currentThread().getName(); while(true){ System.out.println(name); try{ Thread.sleep(1000); }catch(InterruptException e){ } // state가 STOPPED이면 checkState가 true를 변환해서 while문을 벗어나게 됩니다. if(checkState()){ break; } } } public synchronized void setState(int state){ this.state = state; // state가 SUSPENDED였다가 RUNNING으로 변경되면, notify()를 호출합니다. if(state = RUNNING){ notify(); }else{ th.interru } } public synchronized boolean checkState(){ // state가 SUSPENDED면 wait를 호출해서 쓰레드를 대기상태로 만듬 while(state==SUSPENDED){ try{ wait(); }catch(InterruptedException e){ } } // state가 STOPPED이면 true를, 그 외는 false를 리턴합니다. return state == STOPPED; } public void suspend(){ setState(SUSPENDED); } public void resume(){ setState(RUNNING); } public void stop(){ setState(STOPPED); } public void start(){ th.start(); } } | cs |
[출처] [java] wait()와 notify()|작성자 Simpolor
'JAVA > JAVA 스레드' 카테고리의 다른 글
[java] 쓰레드의 동기화 (0) | 2017.11.02 |
---|---|
[java] 쓰레드의 실행제어 (0) | 2017.11.02 |
[java] 데몬 쓰레드 (0) | 2017.11.01 |
[java] 쓰레드 그룹 (0) | 2017.11.01 |
[java] 쓰레드의 우선순위 (0) | 2017.11.01 |
[java] 싱글쓰레드와 멀티쓰레드 (0) | 2017.11.01 |
[java] start()와 run() (0) | 2017.11.01 |
[java] 쓰레드 구현 및 실행 (0) | 2017.11.01 |