Java 입문 | 스레드(Thread) | Thread 우선순의


Object 클래스의 동기 제어

  • final void wait()
    • 다른 스레드는 notify() 또는 notifyAll()가 호출 때까지 스레드를 대기시킨다.
    • 동기화 영역에서 락을 풀고 Wait-Set영역 (공유객체별 존재)으로 이동시킨다.
  • final void wait(long timeout)
    • wait()의 타임아웃 버전이다.
  • final void notify()
    • 이 객체의 대기중의 thread를 1개 재개한다. 재개하는 재개 대상은 선택할 수 없다.
    • Wait-Set 영역에 있는 쓰레드를 깨워서 실행할 수 있도록 한다.
    • notify()는 랜덤이라 내가 원하는 애 말고 다른 애들을 깨울 수도 있다.
  • final void notifyAll()
    • 이 객체의 대기중의 모든 thread를 재개한다.
    • notifyAll()은 Wait-Set에 있는 전부를 깨운다.
  • wait, notify, notifyAll 모두 동기화 영역에서만 실행 가능하다.
  • Object 클래스에서 제공하는 메서드이다
package com.devkuma.basic.thread.wait;

public class ThreadA extends Thread {
    // 해당 쓰레드가 실행되면 자기 자신의 모니터링 락을 획득
    // 5번 반복하면서 0.5초씩 쉬면서 total에 값을 누적
    // 그후에 notify()메소드를 호출하여 wiat하고 있는 쓰레드를 깨운다.
    int total;

    @Override
    public void run() {
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                System.out.println(i + "를 더합니다.");
                total += i;
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            notify();
        }
    }

    public static void main(String[] args) {
        // 쓰레드 A를 생성후에 start한다.
        // 해당 쓰레드가 실행되면, 해당 쓰레드는 run 메소드 안에서 자신의 모니터링 락을 획득
        ThreadA a = new ThreadA();
        a.start();

        // b에 대하여 동기화 블럭을 설정
        // 만약 main 쓰레드가 아래의 블록을 위의 Thread보다 먼저 실행되었다면 wait를 하게 되면서 모니터링 락을 놓고 대기
        synchronized (a) {
            try {
                // b.wait()메소드를 호출.
                // 메인쓰레드는 정지
                // ThreadA가 5번 값을 더한 후 notify를 호출하게 되면 wait에서 깨어남
                System.out.println("b가 완료될때까지 기다립니다.");
                a.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 깨어난 후 결과를 출력
            System.out.println("Total is: " + a.total);
        }
    }
}