通过生产者消费者模式例子讲解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 ...
随机推荐
- Sql Server 2008修改Sa密码
1.用Windows验证模式进入数据库管理器 右键根目录 >>>>属性>>>>左边的安全性 选择sql server 和windows 验证(SQL S ...
- bugly使用
导入: 1.Bugly.framework 2.Security.framework 3.SystemConfiguration.framework 4.libc++.1.dylib 5.libz.1 ...
- android设置多个类似APP其中的一个为默认
05-09 17:01:13.547: I/ActivityManager(3003): START u0 {act=android.intent.action.VIEW cat=[android.i ...
- 二维码识别 android app
TextView类用于展示文本信息 ImageView展示 id:button1(用来显示“扫描二维码”) 布局:fill_parent使布满屏幕(高级版本用match_parent) wrap_co ...
- Big Number--hdu1018(数学)
http://acm.hdu.edu.cn/showproblem.php?pid=1018 题目大意 : 求一个数的阶乘的位数 公式log10(n!)=log10(1)+log10(2)+log1 ...
- 9月15日,YTFCloud,创业圈的技术新宠
成都创业圈近期什么最热? 资本复苏?这本来就是高低起伏规律而已,再说动辄千万的大手笔,对于创业新人.新团队来说太遥远,早期根本无法变现,而资金紧张.项目开发费用超标.没有技术大牛保障等尖锐现实问题能否 ...
- 斯坦福第四课:多变量线性回归(Linear Regression with Multiple Variables)
4.1 多维特征 4.2 多变量梯度下降 4.3 梯度下降法实践 1-特征缩放 4.4 梯度下降法实践 2-学习率 4.5 特征和多项式回归 4.6 正规方程 4.7 正规方程及不可逆性 ...
- Ubuntu下制作ISO文件
利用Ubuntu自带的命令mkisofs就可以制作iso文件,具体方法如下: 1. 如果你是直接从cd压制iso文件的,执行 sudo umount /dev/cdromdd if=/dev/cd ...
- Oracle必须死之奇怪的ORA-06502错误
作为熟练.Net码农以及非熟练Oracle用户很多时候Oracle总给我一种这货就是存心恶心我们的感觉. 虽然不得不承认Oracle是个很(an)好(gui)的产品,但是总有那么好几下被恶心到了.比如 ...
- Orchard Oracle 支持
Orchard v1.7发布了,非常不错的一个升级,为了支持Oracle,基本上和v1.6版差不多,只是工作流相关的表有名字超长问题,改个名就可以了,作了个patch包,发布在: https://or ...