Java中如何使用wait()和notify()方法?
Java 中 wait() 和 notify() 的正确使用方式2025-2026 视角wait()、notify()、notifyAll()是Object 类的原生方法是 Java 最早提供的线程间协作机制属于低级别、重量级的等待/通知机制。核心规则必须全部记住否则 100% 会出问题必须在 synchronized 块/方法中调用wait()、notify()、notifyAll() 都要求当前线程持有同一个对象的监视器锁monitor否则抛出IllegalMonitorStateExceptionwait() 会释放锁调用 wait() 后当前线程会释放对象锁进入该对象的等待队列wait setnotify() / notifyAll() 不释放锁只是唤醒等待队列中的一个/全部线程但不立即把锁给被唤醒的线程只有当前持有锁的线程离开 synchronized 块后被唤醒的线程才有机会竞争锁最经典的写法模板生产级必须这样写// 消费者synchronized(lock){while(conditionNotMet){// 必须用 while不是 if防止虚假唤醒lock.wait();// 释放锁并等待}// 条件满足消费doConsume();}// 生产者synchronized(lock){// 生产doProduce();lock.notify();// 或 notifyAll()// 离开 synchronized 块后被唤醒的线程才有机会抢锁}为什么必须用 while 而不是 if虚假唤醒经典坑虚假唤醒spurious wakeup线程可能在没有被 notify的情况下被系统唤醒极少见但 JVM 规范允许。// 错误写法极易出问题if(queue.isEmpty()){lock.wait();// 被虚假唤醒后可能直接往下执行而队列还是空的}// 正确写法生产环境唯一推荐while(queue.isEmpty()){lock.wait();}完整经典示例生产者-消费者固定大小队列importjava.util.LinkedList;importjava.util.Queue;publicclassProducerConsumer{privatefinalQueueIntegerqueuenewLinkedList();privatefinalintMAX_SIZE10;privatefinalObjectlocknewObject();classProducerimplementsRunnable{Overridepublicvoidrun(){try{while(true){synchronized(lock){while(queue.size()MAX_SIZE){System.out.println(队列已满生产者等待...);lock.wait();}intitem(int)(Math.random()*100);queue.offer(item);System.out.println(生产: item当前大小: queue.size());lock.notifyAll();// 唤醒所有等待的消费者}Thread.sleep(500);// 模拟生产耗时}}catch(InterruptedExceptione){Thread.currentThread().interrupt();}}}classConsumerimplementsRunnable{Overridepublicvoidrun(){try{while(true){synchronized(lock){while(queue.isEmpty()){System.out.println(队列为空消费者等待...);lock.wait();}intitemqueue.poll();System.out.println(消费: item当前大小: queue.size());lock.notifyAll();// 唤醒可能等待的生产者}Thread.sleep(800);// 模拟消费耗时}}catch(InterruptedExceptione){Thread.currentThread().interrupt();}}}publicstaticvoidmain(String[]args){ProducerConsumerpcnewProducerConsumer();newThread(pc.newProducer(),生产者-1).start();newThread(pc.newConsumer(),消费者-1).start();newThread(pc.newConsumer(),消费者-2).start();}}常见错误写法汇总你几乎一定会踩错误写法后果正确做法在 synchronized 外面调用 wait()IllegalMonitorStateException必须在 synchronized 内用 if 判断条件而不是 while虚假唤醒导致逻辑错误永远用 while只用 notify() 而不用 notifyAll()可能导致部分线程永久等待信号丢失多消费者/生产者场景用 notifyAllnotify() 后立即修改共享变量可能导致被唤醒线程看到旧状态修改完再 notify不同对象上 wait/notify线程永远唤不醒必须用同一个锁对象2025–2026 年真实项目中的选择建议场景推荐工具原因简单生产者-消费者、线程间状态等待wait/notify轻量、无额外依赖需要超时等待Condition.await(long, TimeUnit)ReentrantLock 的 Condition 更灵活大多数现代业务代码BlockingQueueArrayBlockingQueue封装好了 wait/notifyAPI 更安全高并发、复杂条件等待Condition ReentrantLock支持多个等待队列、公平锁、可中断响应式/异步场景CompletableFuture / reactor基本不再用原始 wait/notify一句话总结面试/生产最常问的答案“wait() 和 notify() 必须在同一个对象的 synchronized 块中使用wait() 会释放锁并进入等待队列notify() 只唤醒但不释放锁永远用 while 判断条件多线程协作场景优先考虑 notifyAll()。”如果你有具体的场景比如多个等待条件、带超时的等待、与线程池结合等可以告诉我我可以给你更针对性的写法。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2437212.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!