如何在 Java 中正确使用 wait, notify 和 notifyAll?
简介
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 中正确使用 wait, notify 和 notifyAll?的更多相关文章
- 如何在 Java 中正确使用 wait, notify 和 notifyAll(转)
wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视.本文对这些关键字的使用进行了描述. 在 Java 中可以用 wait ...
- 如何在 Java 中正确使用 wait, notify 和 notifyAll – 以生产者消费者模型为例
wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视.本文对这些关键字的使用进行了描述. 在 Java 中可以用 wait ...
- 如何在Java中测试类是否是线程安全的
通过优锐课的java核心笔记中,我们可以看到关于如何在java中测试类是否线程安全的一些知识点汇总,分享给大家学习参考. 线程安全性测试与典型的单线程测试不同.为了测试一个方法是否是线程安全的,我们需 ...
- 如何在JAVA中实现一个固定最大size的hashMap
如何在JAVA中实现一个固定最大size的hashMap 利用LinkedHashMap的removeEldestEntry方法,重载此方法使得这个map可以增长到最大size,之后每插入一条新的记录 ...
- 如何在java中使用sikuli进行自动化测试
很早之前写过一篇介绍sikuli的文章.本文简单介绍如何在java中使用sikuli进自动化测试. 图形脚本语言sikuli sikuli IDE可以完成常见的单击.右击.移动到.拖动等鼠标操作,ja ...
- 如何在Java中调用Python代码
有时候,我们会碰到这样的问题:与A同学合作写代码,A同学只会写Python,而不会Java, 而你只会写Java并不擅长Python,并且发现难以用Java来重写对方的代码,这时,就不得不想方设法“调 ...
- 如何在java中跳出当前多重嵌套循环?有几种方法?
如何在java中跳出当前多重嵌套循环?有几种方法? - 两种方法 - 1.在外层循环定义标记 ok: for(int i=0;i<100;i++){ ...
- 用代码说话:如何在Java中实现线程
并发编程是Java语言的重要特性之一,"如何在Java中实现线程"是学习并发编程的入门知识,也是Java工程师面试必备的基础知识.本文从线程说起,然后用代码说明如何在Java中实现 ...
- 如何在 Java 中实现无向环和有向环的检测
无向环 一个含有环的无向图如下所示,其中有两个环,分别是 0-2-1-0 和 2-3-4-2: 要检测无向图中的环,可以使用深度优先搜索.假设从顶点 0 出发,再走到相邻的顶点 2,接着走到顶点 2 ...
随机推荐
- LR函数基础(二)
(一)用到的函数: (1) web_set_option() //重定向设置 (2)web_reg_save_param和custom_request都常于处理参数的动态生成. web_reg_s ...
- iOS-夜间模式(换肤设置)
概述 iOS 开发中有时候会有夜间模式(换肤设置)的需求, 主要是更改相关颜色操作每次切换夜间/白天模式时,都会发出通知给所有ViewController,让它们切换到相应的主题. 详细 代码下载:h ...
- AsyncTask和AsyncQueryHandler之比较
定义AsyncTask子类 private class LoadContactsTask extends AsyncTask<Void, Void, List<TxrjContact> ...
- (一)Linux实操之——权限、任务调度、磁盘分区
1. 权限 1.1 查看权限 通过ls -l命令可以看到文件的详细信息 下面以一条信息解释各个位置字符的作用 -rwxr--r--. 1 root root 32 6月 18 10:15 choose ...
- 【JAVA】Exception in thread "main" java.lang.NoClassDefFoundError
java新手经常会遇到这个问题. 环境变量配置正确,eclipse下可以正常编译运行,命令行下可以使用javac生成.class文件,但是在当前目录运行的时候提示: 分析报错,可以发现系统从Pack文 ...
- pythonl练习笔记——python线程的GIL
python线程中的全局解释器锁GIL(Global Interpreter Lock) python-->支持多线程-->同步和互斥-->加锁-->解释器加锁-->解释 ...
- IDLE经常使用快捷键汇总
IDLE(An Integrated DeveLopment Environment for Python)是Python自带的编译器,在刚開始学习的人,或写小程序,或用于验证的时候,经经常使用到!假 ...
- Unity3D中组件事件函数的运行顺序
事件函数的运行顺序 Unity 脚本中有很多按预设顺序以脚本身份执行的事件函数. 其执行顺序例如以下: 载入第一个场景 启动场景时调用这些函数(为场景中的每一个对象调用一次). Awake: 始终在调 ...
- 两种方式— 在hive SQL中传入参数
第一种: sql = sql.format(dt=dt) 第二种: item_third_cate_cd_list = " 发发发 " ...... ""&qu ...
- Windwos配置Maven环境变量
下载Maven插件:http://maven.apache.org/download.cgi 添加环境变量: MAVEN_HOMEE:\Program Files\Apache Software Fo ...