Java에서 객체에 대해 wait() 메서드를 호출하면 현재 스레드는 다른 스레드가 해당 객체의 notify() 또는 notifyAll() 메서드를 호출할 때까지 대기 상태로 전환됩니다. 반면 wait(long timeout)은 다른 스레드가 notify() 또는 notifyAll()을 호출하거나, 지정된 시간(timeout)이 경과하는 경우 두 조건 중 하나라도 충족되면 대기에서 벗어납니다.
wait() 메서드의 동작
아래 프로그램처럼 객체에 대해 wait()를 호출하면 스레드는 실행(running) 상태에서 대기(waiting) 상태로 전환됩니다. 이후 다른 스레드가 notify() 또는 notifyAll()을 호출해야만 실행 가능(runnable) 상태로 돌아갈 수 있습니다. 만약 아무도 깨워주지 않으면 스레드는 영원히 대기하게 되며, 이 경우 교착 상태(deadlock)가 발생할 수 있습니다.
예제 코드
class MyRunnable implements Runnable {
public void run() {
synchronized(this) {
System.out.println("In run() method");
try {
this.wait();
System.out.println("Thread in waiting state, waiting for some other threads on same object to call notify() or notifyAll()");
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
public class WaitMethodWithoutParameterTest {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable, "Thread-1");
thread.start();
}
}실행 결과
In run() method
출력 결과를 보면 "In run() method"만 출력되고 프로그램이 종료되지 않습니다. 이는 스레드가 wait() 호출 후 무기한 대기 상태에 머물러 있기 때문입니다.
wait(long) 메서드의 동작
반면 아래 프로그램처럼 객체에 대해 wait(1000)을 호출하면 스레드는 역시 실행 상태에서 대기 상태로 전환됩니다. 하지만 notify()나 notifyAll()이 호출되지 않더라도, 지정한 시간(여기서는 1000밀리초 = 1초)이 경과하면 스레드는 자동으로 대기 상태에서 실행 가능(runnable) 상태로 복귀합니다.
예제 코드
class MyRunnable implements Runnable {
public void run() {
synchronized(this) {
System.out.println("In run() method");
try {
this.wait(1000);
System.out.println("Thread in waiting state, waiting for some other threads on same object to call notify() or notifyAll()");
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
public class WaitMethodWithParameterTest {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable, "Thread-1");
thread.start();
}
}실행 결과
In run() method Thread in waiting state, waiting for some other threads on same object to call notify() or notifyAll()
정리: 두 메서드의 핵심 차이
- wait(): 매개변수가 없으므로 다른 스레드가 notify() 또는 notifyAll()을 호출하기 전까지 무기한 대기합니다.
- wait(long timeout): notify()/notifyAll() 호출 또는 지정된 시간 경과 중 하나라도 발생하면 대기를 해제합니다.
두 메서드 모두 동기화(synchronized) 블록이나 메서드 내부에서 호출해야 하며, 그렇지 않으면 IllegalMonitorStateException이 발생한다는 점도 함께 기억해 두시기 바랍니다.