如何在 Java 中正确使用 wait, notify 和 notifyAll?
JAVA 如何 正确 WAIT notify 使用 notifyAll
2023-09-14 08:57:25 时间
简介
wait,notify,notifyAll,都是属于object对象提供的方法,但在实际工作中怎么使用这几个方法,确是很多程序员清楚,不够明白,在群里问,有人说,哪个线程想wait,就用
需等待线程.wait(),就跟Thread.sleep()一样,唤醒也一样,这样显然是不对的。
在 Java 中可以用 wait、notify 和 notifyAll 来实现线程间的通信。。举个例子,如果你的Java程序中有两个线程——即生产者和消费者,那么生产者可以通知消费者,让消费者开始消耗数据,因为队列缓 冲区中有内容待消费(不为空)。相应的,消费者可以通知生产者可以开始生成更多的数据,因为当它消耗掉某些数据后缓冲区不再为满。
1、废话不多说,直接看demo吧
package hello.wait_notify; import java.util.LinkedList; import java.util.List; import java.util.Random; import java.util.concurrent.ConcurrentLinkedQueue; /** * Created by jacky on 2017/3/25 0025. */ public class Waint_Notify { public static void main(String args[]) { ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue(); int maxSize = 10; Thread producer = new Producer(queue, maxSize, "PRODUCER"); Thread consumer = new Consumer(queue, maxSize, "CONSUMER"); producer.start(); consumer.start(); } static class Producer extends Thread { private ConcurrentLinkedQueue queue; private int maxSize; public Producer(ConcurrentLinkedQueue queue, int maxSize, String name) { super(name); this.queue = queue; this.maxSize = maxSize; } @Override public void run() { while (true) { synchronized (queue) { while (queue.size() == maxSize) { try { System.out.println("队列中已经满了,等待消费者消费!"); queue.wait(); } catch (Exception ex) { ex.printStackTrace(); } } Random random = new Random(); int i = random.nextInt(); System.out.println("Producing value : " + i); queue.add(i); queue.notifyAll(); } } } } static class Consumer extends Thread { private ConcurrentLinkedQueue queue; private int maxSize; public Consumer(ConcurrentLinkedQueue queue, int maxSize, String name) { super(name); this.queue = queue; this.maxSize = maxSize; } @Override public void run() { while (true) { synchronized (queue) { while (queue.isEmpty()) { System.out.println("队列已经空了,等待生产者放数据" ); try { queue.wait(); } catch (Exception ex) { ex.printStackTrace(); } } System.out.println("Consuming value : " + queue.remove()); queue.notifyAll(); } } } } }
2、结果
3、总结
1. 你可以使用wait和notify函数来实现线程间通信。你可以用它们来实现多线程(>3)之间的通信。
2. 永远在synchronized的函数里使用wait、notify和notifyAll,不然Java虚拟机会生成 IllegalMonitorStateException。
3. 永远在while循环里而不是if语句下使用wait。这样,循环会在线程睡眠前后都检查wait的条件,并在条件实际上并未改变的情况下处理唤醒通知。
4. 永远在多线程间共享的对象(在生产者消费者模型里即缓冲区队列)上使用wait。
5. 基于前文提及的理由,更倾向用 notifyAll(),而不是 notify()。
相关文章
- java转换字符串为时间_JAVA字符串转日期或日期转字符串
- java用什么软件_Java编程什么软件最好用?
- java对象组声明_如何在Java中声明对象数组?
- java中打印数组的方法_Java数组方法–如何在Java中打印数组
- eclipse怎么导入java文件_Eclipse如何导入JAVA工程?如何将项目导入Eclipse中?
- java笔试题_一道简单的 Java 笔试题,但值得很多人反思
- java运行环境_如何搭建Java运行环境?
- C++和Java哪个比较好入门?初学者该如何选择?
- java环境_Java基础篇——环境配置
- MySQL字段类型如何转为java_Java JDBC中,MySQL字段类型到JAVA类型的转换
- java获取服务器路径_Java获取此次请求URL以及服务器根路径的方法「建议收藏」
- java 自定义类加载器_JAVA中如何使用应用自定义类加载器「建议收藏」
- Java map转实体类_java实体类转json
- Java 中如何限制方法的返回时间
- Java中的Lambda是如何实现的
- Java连接MySQL:实现数据互通(java如何连接mysql)
- Java 连接 MySQL 数据库简易实现(java连mysql)
- Oracle 视图 DBA_JAVA_LAYOUTS 官方解释,作用,如何使用详细说明
- 学习如何使用Linux环境运行Java程序(linux下的java)
- 数据库简易指南:如何使用 Java 连接 MySQL 数据库(java连接mysql)
- 服务如何在Linux上快速关闭Java服务(linux关闭java)
- 时间设置Java中Redis如何设置过期时间(redisjava过期)
- 使用Java远程控制Linux 实现简单、高效的服务器管理(java控制linux)
- 如何在Linux系统中指定Java版本(linux指定java)
- Java程序如何在Linux上顺利部署?快来了解一下!(java部署到Linux)