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

Java wait方法工作原理解析及相关代码疑问咨询

Java wait() 方法工作原理及代码解析

Hey there! Let's break down how Java's wait() method works and walk through your code step by step.

先搞懂wait()的核心逻辑

wait()是Object类的方法(不是Thread类的!这点很容易搞混),它的作用是让当前线程暂时放弃对象锁,进入该对象的等待队列,直到被其他线程唤醒。使用它有几个硬性规则:

  • 必须在synchronized代码块或方法里调用,因为调用前当前线程必须持有该对象的锁
  • 调用wait()时,线程会主动释放持有的对象锁,进入WAITING状态
  • 被其他线程调用同一个对象的notify()或notifyAll()唤醒后,线程不会立刻执行,需要重新竞争并拿到对象锁,才能继续执行wait()之后的代码
  • 如果一直没人唤醒,线程会一直等下去,实际开发中通常会配合while循环检查条件,防止「虚假唤醒」(比如线程被唤醒但条件还不满足)

你的代码解析(先补全了缺失的run方法)

首先我把你没写完的ThreadImpl的run()方法补全了,这样代码能完整运行并体现wait/notify的逻辑:

public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        ThreadImpl thr = new ThreadImpl();
        thr.start();
        Thread.sleep(1000);
        synchronized(thr){
            System.out.println( "MAIN "+thr.hashCode());
            System.out.println("Main -->got the lock");
            thr.wait();
            System.out.println("Main -->Done with waiting");
        }
    }
}

class ThreadImpl extends Thread{
    public synchronized void sayHello(){
        System.out.println("Say hello ");
    }

    @Override
    public void run() {
        synchronized (this) {
            System.out.println("ThreadImpl --> got the lock");
            try {
                Thread.sleep(2000); // 模拟耗时业务操作
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.notify(); // 唤醒等待在当前对象上的线程
            System.out.println("ThreadImpl --> notified waiting thread");
        }
    }
}

代码执行的完整流程

  1. 主线程启动子线程:主线程创建ThreadImpl实例thr,调用thr.start()后,子线程进入就绪状态,等待CPU调度。
  2. 主线程休眠1秒:主线程调用Thread.sleep(1000),这段时间里子线程开始执行run()方法:
    • 子线程进入synchronized(this)块,成功拿到thr对象的锁,打印ThreadImpl --> got the lock
    • 子线程休眠2秒,模拟业务操作,此时它还持有thr的锁。
  3. 主线程等待锁:主线程休眠1秒后醒来,进入synchronized(thr)块,但此时子线程还拿着thr的锁,所以主线程会阻塞,等待锁释放。
  4. 子线程唤醒主线程并释放锁:子线程休眠2秒结束,调用this.notify(),把等待在thr对象上的主线程唤醒,但子线程此时还没释放锁,会继续打印ThreadImpl --> notified waiting thread,然后退出synchronized块,释放thr的锁。
  5. 主线程恢复执行:主线程拿到thr的锁后,从thr.wait()的位置继续执行,打印Main -->Done with waiting,最后退出synchronized块。

几个容易踩坑的点

  • 别把wait()和sleep()搞混:sleep()是Thread类的方法,调用时不会释放锁;wait()是Object类的,调用时会释放锁。
  • 必须在持有锁的情况下调用wait():如果直接在synchronized块外调用thr.wait(),会抛出IllegalMonitorStateException,因为当前线程没持有thr的锁。
  • 虚假唤醒问题:实际开发中不要用if判断条件,要用while循环,比如:
    synchronized(thr) {
        while(条件不满足) {
            thr.wait();
        }
        // 执行逻辑
    }
    
    这样就算线程被虚假唤醒,也会重新检查条件,继续等待。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:49:27