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"); } } }
代码执行的完整流程
- 主线程启动子线程:主线程创建
ThreadImpl实例thr,调用thr.start()后,子线程进入就绪状态,等待CPU调度。 - 主线程休眠1秒:主线程调用
Thread.sleep(1000),这段时间里子线程开始执行run()方法:- 子线程进入
synchronized(this)块,成功拿到thr对象的锁,打印ThreadImpl --> got the lock - 子线程休眠2秒,模拟业务操作,此时它还持有
thr的锁。
- 子线程进入
- 主线程等待锁:主线程休眠1秒后醒来,进入
synchronized(thr)块,但此时子线程还拿着thr的锁,所以主线程会阻塞,等待锁释放。 - 子线程唤醒主线程并释放锁:子线程休眠2秒结束,调用
this.notify(),把等待在thr对象上的主线程唤醒,但子线程此时还没释放锁,会继续打印ThreadImpl --> notified waiting thread,然后退出synchronized块,释放thr的锁。 - 主线程恢复执行:主线程拿到
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
相关产品推荐
相关产品推荐

