You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java线程wait()方法行为解析及相关疑难问题咨询

关于Java Thread.wait()的三段代码行为解析

第一段代码:未加synchronized导致IllegalMonitorStateException

直接调用thread.wait()时抛出IllegalMonitorStateException,核心原因是**wait()方法的强制规则**:调用任意对象的wait()前,当前线程必须持有该对象的监视器锁(即必须在synchronized块或synchronized方法中操作这个对象)。

这段代码里,主线程没有通过synchronized获取thread对象的锁就调用了wait(),违反规则,因此JVM直接抛出异常。

代码示例:

class Scratch {
  public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(() -> {
      System.out.println("Inside thread");
    });

      thread.wait();

  }
}

异常信息:

Exception in thread "main" java.lang.IllegalMonitorStateException: current thread is not owner
    at java.base/java.lang.Object.wait0(Native Method)
    at java.base/java.lang.Object.wait(Object.java:366)
    at java.base/java.lang.Object.wait(Object.java:339)
    at Scratch.main(scratch_125.java:8)

第二段代码:持有锁但无人唤醒导致永久阻塞

添加synchronized (thread)块后,主线程获取了thread对象的锁,满足wait()的调用条件,因此不再抛出异常。但主线程会一直阻塞在thread.wait()处,原因是:

  • wait()执行时会释放当前持有的锁,让线程进入等待状态,直到有其他线程调用该对象的notify()或notifyAll()唤醒它。
  • 这段代码里thread未调用start(),线程永远不会启动,更不会终止。而只有当Thread对象关联的线程终止时,JVM才会自动调用该对象的notifyAll()。没有任何线程来唤醒主线程,所以它会一直等待下去。

你误以为未启动线程调用wait()会抛异常,其实wait()是Object类的方法,和线程是否启动无关——只要当前线程持有对象锁,就能调用,不会因线程未启动抛出异常。

代码示例:

class Scratch {
  public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(() -> {
      System.out.println("Inside thread");
    });


    synchronized (thread) {
      thread.wait();             // keeps waiting here
    }

    System.out.println("Main thread working fine?"); // never reached here

  }
}

第三段代码:线程终止触发自动唤醒,wait()结束阻塞

添加thread.start()后,子线程启动并执行,当它运行完毕(包括sleep 5秒后),线程进入终止状态。此时JVM会自动调用该Thread对象的notifyAll()方法,唤醒所有在该对象上等待的线程——也就是主线程。因此主线程的wait()被唤醒,继续执行后续的打印语句。

注意:虽然这里wait()起到了等待线程结束的效果,但这不是wait()的正确用法,等待线程终止应该用thread.join()。这里的行为是JVM对Thread对象的特殊处理,不要依赖这个特性实现线程同步。

代码示例:

class Scratch {
  public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(() -> {
      System.out.println("Inside thread");

      try {
        Thread.sleep(5000);
      } catch (InterruptedException e) {
        throw new RuntimeException(e);
      }
    });


    thread.start();

    synchronized (thread) {
      thread.wait();
    }

    System.out.println("Main thread working fine?");

  }
}

内容的提问来源于stack exchange,提问作者Mohit Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 18:05:14