通过生产者消费者模式例子讲解Java基类方法wait、notify、notifyAll
wait(),notify()和notifyAll()都是Java基类java.lang.Object的方法。
通俗解释
wait():在当前线程等待其它线程唤醒。
notify(): 唤醒一个线程正在等待这个对象的监视器。
notifyAll(): 唤醒在这个对象监视器上等待的所有线程。
这三个方法,都是Java语言提供的实现线程间阻塞(Blocking)和控制进程内调度(inter-process communication)的底层机制。
下面通过一个生产者/消费者的例子来讲解这三个方法的使用
/**
* 消费者
* Created by Wiki on 16/1/28.
*/
public class Customer implements Runnable {
private String name;
private Channel channel; public Customer(String name, Channel channel) {
this.name = name;
this.channel = channel;
} @Override
public void run() {
while (true) {
Good good = channel.get();
if (good != null) {
System.out.println(name + " 获得商品:" + good.getName());
} else {
synchronized (channel) {
try {
System.out.println(name + " 进入等待");
channel.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
/**
* 生产者
* Created by Wiki on 16/1/28.
*/
public class Producer implements Runnable {
private static volatile int goodNumber = 0; private String name;
private Channel channel; public Producer(String name, Channel channel) {
this.name = name;
this.channel = channel;
} @Override
public void run() {
while (true) {
int sleep = new Random().nextInt(2000);
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
Good good = new Good("商品-编号" + (++goodNumber));
System.out.println(name + " 生产商品:" + good.getName());
channel.put(good);
}
}
}
/**
* 商品
* Created by Wiki on 16/1/28.
*/
public class Good {
private String name; public Good(String name) {
this.name = name;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}
/**
* 消费通道
* Created by Wiki on 16/1/28.
*/
public class Channel {
private Queue<Good> goodList = new LinkedList<>(); public synchronized Good get() {
if (goodList.size() == 0) {
return null;
}
Good good = goodList.remove();
return good;
} public synchronized void put(Good good) {
goodList.add(good);
// notifyAll();
notify();
}
}
public class Main {
public static void main(String[] args) {
Channel channel = new Channel();
new Thread(new Producer("生产者1", channel)).start();
new Thread(new Producer("生产者2", channel)).start();
new Thread(new Producer("生产者2", channel)).start();
new Thread(new Customer("消费者1", channel)).start();
new Thread(new Customer("消费者2", channel)).start();
new Thread(new Customer("消费者3", channel)).start();
}
}
运行结果分析一(notify):
每次生产一个商品调用notify时,都只唤醒一个消费者进行消费,唤醒原则是从等待时间最长的开始。
消费者1 进入等待
消费者2 进入等待
消费者3 进入等待
生产者1 生产商品:商品-编号1
消费者1 获得商品:商品-编号1
消费者1 进入等待
生产者2 生产商品:商品-编号2
消费者2 获得商品:商品-编号2
消费者2 进入等待
生产者2 生产商品:商品-编号3
消费者3 获得商品:商品-编号3
消费者3 进入等待
生产者1 生产商品:商品-编号4
消费者1 获得商品:商品-编号4
消费者1 进入等待
生产者1 生产商品:商品-编号5
消费者2 获得商品:商品-编号5
消费者2 进入等待
...
运行结果分析二(把notify改成notifyAll):
每生产一件商品时调用notifyAll,都会把所有的消费者唤醒。
消费者1 进入等待
消费者3 进入等待
消费者2 进入等待
生产者2 生产商品:商品-编号1
消费者3 进入等待
消费者2 获得商品:商品-编号1
消费者1 进入等待
消费者2 进入等待
生产者2 生产商品:商品-编号2
消费者2 获得商品:商品-编号2
消费者1 进入等待
消费者3 进入等待
消费者2 进入等待
生产者2 生产商品:商品-编号3
消费者2 获得商品:商品-编号3
...
来源:http://www.taoweiji.cn/index.php/archives/112
通过生产者消费者模式例子讲解Java基类方法wait、notify、notifyAll的更多相关文章
- Java设计模式—生产者消费者模式(阻塞队列实现)
生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...
- Java 生产者消费者模式详细分析
*/ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...
- java ReentrantLock结合条件队列 实现生产者-消费者模式 以及ReentratLock和Synchronized对比
package reentrantlock; import java.util.ArrayList; public class ProviderAndConsumerTest { static Pro ...
- 【多线程】java多线程实现生产者消费者模式
思考问题: 1.为什么用wait()+notify()实现生产者消费者模式? wait()方法可以暂停线程,并释放对象锁 notify()方法可以唤醒需要该对象锁的其他线程,并在执行完后续步骤,到了s ...
- java 多线程 22 :生产者/消费者模式 进阶 利用await()/signal()实现
java多线程15 :wait()和notify() 的生产者/消费者模式 在这一章已经实现了 wait/notify 生产消费模型 利用await()/signal()实现生产者和消费者模型 一样 ...
- 基于Java 生产者消费者模式(详细分析)
Java 生产者消费者模式详细分析 本文目录:1.等待.唤醒机制的原理2.Lock和Condition3.单生产者单消费者模式4.使用Lock和Condition实现单生产单消费模式5.多生产多消费模 ...
- Java设计模式之生产者消费者模式
Java设计模式之生产者消费者模式 博客分类: 设计模式 设计模式Java多线程编程thread 转载 对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一 ...
- java 多线程并发系列之 生产者消费者模式的两种实现
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...
- java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】
java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...
随机推荐
- ntp -q 输出说明
-bash-3.00# ntpq -p remote refid st t when poll reach delay offset ...
- Github两步认证
获取密钥:ssh-keygen -t rsa 切换到公钥所在路径:cd .ssh 查看该路径下的所有文件:ls 查看公钥:cat id_rsa.pub 获取密钥之后,去https://github. ...
- Unity5的AssetBundle的一点使用心得
昨天一位朋友在我这里留言,想让我写点Unity5的AssetBundle心得.于是我就看了相关的介绍,和自己确切的做了一次.下面来谈谈所谓的心得. 如果你觉得自己对AssetBundle不熟悉,建议先 ...
- php public protected private属性实例详解
php 类中函数和类变量都有三个属性:public protected private,具体什么时候使用什么属性好纠结,特意找了个实例,这样看起来更清晰. public 表示全局,类内部外部子类都可以 ...
- JS-字符串操作,查找显示高亮
<!DOCTYPE HTML><html><head><meta http-equiv="Content-Type" content=&q ...
- Android性能优化方法(六)
ContentProvider优化改进 1.索引简单的说,索引就像书本的目录,目录可以快速找到所在页数,数据库中索引可以帮助快速找到数据,而不用全表扫描,合适的索引可以大大提高数据库查询的效率.(1) ...
- Learning OpenCV
1. 读取图片 opencv/highgui.h 2. 读取视频 opencv/cv.h opencv/highgui.h 3. 高斯平滑滤波 4. 灰度单通道与边缘检测 5. 摄像头打开 void ...
- Memcache的使用基本介绍
Memcache学习总结2-Memcache的使用基本介绍 上一次总结中我们已经安装部署好了Memcached,并且把PHP扩展Memcache也安装好了,这一节我们详细学习一下PHP扩展Memcac ...
- AndroidStudio Lod.d在LogCat中不输出
今天Log.d无论怎样都没有输出. 要在手机开发者选项那开启权限,莫名其妙,之前一直都没事的,具体操作参考:http://jingyan.baidu.com/article/84b4f56597e7b ...
- Ascii Design 1.0.2,好玩的 ASCII 字符设计工具
Ascii Design 1.0.2 可检查系统是否已安装 figlet 包(对非 Windows 用户),对代码做了一些改进,修复了使用 Qt 4.8.x 时的编译警告信息. Ascii Desig ...