Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

Java의 wait()와 sleep() 메소드 차이점 완벽 정리

Java 멀티스레딩 프로그래밍에서는 스레드의 실행을 일시적으로 중단해야 하는 경우가 자주 발생합니다. 이때 가장 많이 사용되는 두 가지 메소드가 바로 sleep()wait()입니다. 두 메소드 모두 스레드를 대기 상태로 만들지만, 동작 방식과 용도에는 중요한 차이가 있습니다.

wait()와 sleep()의 주요 차이점

1. 소속 클래스와 호출 방식
sleep() 메소드는 Thread 클래스의 static 메소드로, 현재 실행 중인 스레드를 "Non-Runnable(실행 불가)" 상태로 전환합니다. 반면 wait()는 Object 클래스에 정의된 인스턴스(final) 메소드로, 특정 객체에 대해 호출되며 해당 객체의 락에만 영향을 미칩니다.

2. 스레드가 다시 깨어나는 조건
sleep()은 지정한 시간이 경과하거나 다른 스레드가 interrupt() 메소드를 호출하면 깨어납니다. 반면 wait()는 지정한 시간이 경과하거나 같은 객체에 대해 notify() 또는 notifyAll() 메소드가 호출될 때 깨어납니다.

3. 락(Lock) 해제 여부
가장 중요한 차이점입니다. sleep()은 대기하는 동안에도 보유하고 있는 락(lock)이나 모니터(monitor)를 해제하지 않습니다. 따라서 다른 스레드는 해당 객체의 동기화 블록에 접근할 수 없습니다. 반면 wait()는 대기 상태에 들어갈 때 락과 모니터를 해제하므로, 다른 스레드가 같은 객체의 락을 획득하여 작업을 수행할 수 있습니다.

sleep() 메소드 문법

public static void sleep(long millis) throws InterruptedException

wait() 메소드 문법

public final void wait() throws InterruptedException

참고로 wait()는 반드시 synchronized 블록이나 synchronized 메소드 내부에서 호출해야 하며, 락을 보유하지 않은 상태에서 호출하면 IllegalMonitorStateException이 발생합니다.

예제 코드

public class ThreadTest implements Runnable {
    private int number = 10;
    public void methodOne() throws Exception {
        synchronized(this) {
            number += 50;
            System.out.println("Number in methodOne(): " + number);
        }
    }
    public void methodTwo() throws Exception {
        synchronized(this) {
            Thread.sleep(2000); // calling sleep() method 
            this.wait(1000); // calling wait() method
            number *= 75;
            System.out.println("Number in methodTwo(): " + number);
        }
    }
    public void run() {
        try {
            methodOne();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws Exception {
        ThreadTest threadTest = new ThreadTest();
        Thread thread = new Thread(threadTest);
        thread.start();
        threadTest.methodTwo();
    }
}

실행 결과

Number in methodOne(): 60
Number in methodTwo(): 4500

실행 결과를 살펴보면, 먼저 락을 획득한 methodOne()이 실행되어 number 값이 10 + 50 = 60이 됩니다. 이후 methodTwo()가 락을 획득한 뒤 sleep(2000)으로 잠시 대기하고, wait(1000)을 호출한 후 number에 75를 곱해 최종적으로 4500이 출력됩니다. 이 예제는 하나의 객체(this)에 대해 synchronized 블록이 어떻게 순차적으로 실행되는지 보여줍니다.

정리

sleep()은 단순히 일정 시간 동안 스레드 실행을 멈추고 싶을 때 사용하고, wait()는 스레드 간 통신(inter-thread communication)을 통해 특정 조건이 충족될 때까지 대기해야 할 때 사용합니다. 락을 유지한 채 잠시 멈추려면 sleep(), 락을 반납하며 다른 스레드의 신호를 기다리려면 wait()를 선택하는 것이 바람직합니다.