Java生产者与消费者(下)
本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!
上一讲我们让消费者和生产者都各停1毫秒,实际上大多并不是这样的。第二讲,我们讲一个极端的例子和一个正常的例子,假设您已经看过上一讲,我们只改变Consumer和Producer,来看结果。
名词解释
wait:当前线程不运行,处理等待状态,等待notify;所以也不会往下执行。
您可能会有疑问前例中的为什么要用while循环而非if语句?
主要是防止多线程操作时,例桌子已经占满,两个生产线程均处理等待状态,但消费线程通过notifyAll打开其等待状态,就造成生产过量的蛋糕,而导致生产消费模式失败,所以不能用if语句。
sleep:暂停当前线程若干时间,之后继续运行
Special Sample:生产者和消费者均不加sleep
Result:
Produce1 produce:1
Produce2 produce:2
Produce1 produce:3
Produce1 produce:4
Produce1 produce:5
Produce1 begin to wait !
Consumer1 consume:5
Consumer1 consume:4
Consumer1 consume:3
Consumer1 consume:2
Consumer1 consume:1
Consumer1 begin to wait !
Produce1 stop waiting !
Produce1 produce:1Produce1 produce:2
Produce2 produce:3
Produce2 produce:4
Produce2 produce:5
Produce2 begin to wait !
Consumer2 consume:5
Consumer2 consume:4
Consumer2 consume:3
Consumer2 consume:2
Consumer2 consume:1
Consumer2 begin to wait !
Produce2 stop waiting !
Produce2 produce:1
Produce2 produce:2
Produce2 produce:3
Produce2 produce:4
Produce2 produce:5
Produce2 begin to wait !
Produce1 begin to wait !
Consumer1 stop waiting !
Consumer1 consume:5
Consumer1 consume:4
Consumer1 consume:3
Consumer1 consume:2
Consumer1 consume:1
Consumer1 begin to wait !
Produce1 stop waiting !
Produce1 produce:1
Produce1 produce:2
Produce1 produce:3
Produce1 produce:4
Produce1 produce:5
Produce1 begin to wait !
Produce2 stop waiting !
Produce2 begin to wait !
Consumer2 stop waiting !
Consumer2 consume:5
Consumer2 consume:4
Consumer2 consume:3
Consumer2 consume:2
Consumer2 consume:1
Consumer2 begin to wait !
Produce2 stop waiting !
Produce2 produce:1
Produce2 produce:2
Produce2 produce:3
Produce2 produce:4
Produce2 produce:5
Produce2 begin to wait !
Produce1 stop waiting !
Produce1 begin to wait !
Consumer1 stop waiting !
Consumer1 consume:5
Consumer1 consume:4
Consumer1 consume:3
Consumer1 consume:2
Consumer1 consume:1
Consumer1 begin to wait !
Produce1 stop waiting !
Produce1 produce:1
Produce1 stop at last !解析:例子很极端,生产和消费均两个线程,A线程在工作时B在等待;
A生产线程生产,B生产线程等待直到A生产完;
A消费线程消费,B消费线程等待直到A消费完;
B生产线程生产,A生产线程等待直到A生产完;
B消费线程消费,A消费线程等待直到A消费完;……
这样一个循环,失去多线程的意义所在(变成了单线程)!
正常的例子:生产可能只需要1毫秒,消费需要2毫秒
Produce1 produce:1
Consumer1 consume:1
Consumer2 begin to wait !//此时Consumer2检测到count为0,所以等待
Produce2 produce:1
Consumer2 stop waiting !//此时Consumer2检测到count已经大于0,所以打开
Consumer2 consume:1
Produce1 produce:1//看,生产与消费是无序的。两者分开,不管你在不在生产,我都要消费,只要蛋糕还有;
Produce2 produce:2//不管你消费不消费,只要桌子还有空的;它们两个均对一种情况负责:桌子和蛋糕形成的映射关系!
Consumer2 consume:2
Consumer1 consume:1
Produce2 produce:1
Produce1 produce:2
Produce2 produce:3
Produce1 produce:4
Consumer1 consume:4
Consumer2 consume:3
Produce1 produce:3
Produce2 produce:4
Produce2 produce:5
Produce1 begin to wait !
Consumer1 consume:5
Produce1 stop waiting !
Produce1 produce:5
Produce2 begin to wait !
Consumer2 consume:5
Produce2 stop waiting !
Produce2 produce:5
Produce2 begin to wait !
Produce1 begin to wait !
Consumer2 consume:5
Produce1 stop waiting !
Produce1 produce:5
Produce2 stop waiting !
Produce2 begin to wait !
Consumer1 consume:5
Produce2 stop waiting !
Produce2 produce:5
Produce1 begin to wait !
Produce2 begin to wait !
Consumer1 consume:5
Consumer1 stop at last !解析:这次我让执行25次即退出虚拟机。
大家可以看到,本次两个生产线程和两个消费线程,在生产和消费的时候都是无序的,无论你要不要停,我都要工作,不能让一个线程一直抓住锁不放,其实这才是多线程本质。
代码如下:
Producer:
public class Producer extends Thread {
Table table;
String threadName; public Producer(String string, Table table) {
// TODO Auto-generated constructor stub
this.table = table;
this.threadName = string;
this.setName(threadName);
} @Override
public void run() {
// TODO Auto-generated method stub
super.run();
try {
while (true) {
table.produce(threadName);
sleep(1);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}消费者:
public class Consumer extends Thread {
Table table;
String threadName; public Consumer(String string, Table table) {
// TODO Auto-generated constructor stub
this.table = table;
this.threadName = string;
this.setName(threadName);
} @Override
public void run() {
// TODO Auto-generated method stub
super.run();
try {
while (true) {
table.consume(threadName);
sleep(2);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Java生产者与消费者(下)的更多相关文章
- Java生产者与消费者(上)
本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 生产与消费者模式,是编程中最常用的模式之一,在多线程中应用比较明显.个人理解:在自助餐厅,厨师在不断 ...
- java生产者与消费者模式
前言: 生产者和消费者模式是我们在学习多线程中很经典的一个模式,它主要分为生产者和消费者,分别是两个线程, 目录 一:生产者和消费者模式简介 二:生产者和消费者模式的实现 声明:本例来源于java经典 ...
- java 生产者 与 消费者的案例
主要理解了两个问题 1.线程数据同步的问题 2.线程交替运行的方式 package ThreadDemo; /** * 生产者与消费者的案例(一,同步的问题,值的问题 二,交替执行的问题) * @au ...
- Java 生产者模式 消费者模式
// The standard idiom for calling the wait synchronized(sharedObject) { while(condition){ sharedObje ...
- Java生产者和消费者问题
容器类Box.java public class Box { private int num = 0; public void put(){ if(num==10){ try { System.out ...
- java生产者,消费者
有很多实现的方法 使用blockingqueue实现 demo import java.util.concurrent.LinkedBlockingQueue; /** * Created by 58 ...
- Windows下RabbitMQ 的下载、配置、Java实现生产者和消费者例子
RabbitMQ是一个轻量级的消息代理中间件,支持多种消息通信协议,支持分布式部署,支持运行于多个操作系统,具有灵活.高可用等特性.RabbitMQ支持多种协议,其中最为重要的是高级消息队列协议(AM ...
- java 生产者消费者问题 并发问题的解决
引言 生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,如下图所示,生产者向空间里存放数据,而消费者取用数据,如果不加以协调可能会出现以下情况: 生产者消费者图 ...
- Java实现生产者和消费者
生产者和消费者问题是操作系统的经典问题,在实际工作中也常会用到,主要的难点在于协调生产者和消费者,因为生产者的个数和消费者的个数不确定,而生产者的生成速度与消费者的消费速度也不一样,同时还要实现生产者 ...
随机推荐
- Host status showing red icon in chronograph, Chronograf主机列表页显示主机状态为红色标志
刚开始全部装好的时候主机显示的状态是绿色的,过了些日子我再打开看的时候就变成红色的了,点击主机进去查看的时候没有了图表数据,大概是这样子的, 在influxdb数据库主机上执行命令curl " ...
- xargs---组合命令的工具
xargs命令是给其他命令传递参数的一个过滤器,也是组合多个命令的一个工具.它擅长将标准输入数据转换成命令行参数,xargs能够处理管道或者stdin并将其转换成特定命令的命令参数.xargs也可以将 ...
- 紫书 习题 10-8 UVa 10622(gcd)
把这个数质因数分解然后求因子个数的gcd就ok了. 一些细节 (1)这道题的质因数不需要存下来,每一次做完取一次gcd就ok了 (2)判断奇偶用ans & 1的时候要加括号, 位运算要注意括号 ...
- 最长回文字串 (The longest palindrome substring)
这两天去学了一下,觉得下面那篇文章写的很好,有例子,比较容易懂,所以转一下. 以下内容来自:hihoCoder: 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互 ...
- jquery中$.get()提交和$.post()提交有区别
jquery中$.get()提交和$.post()提交有区别吗? 相同点:都是异步请求的方式来获取服务端的数据: 异同点: 1.请求方式不同:$.get() 方法使用GET方法来进行异步请求的.$.p ...
- HBase 1.1.2 优化插入 Region预分配
预分Region 与 不预分Region 的测试: 1 不预分Region: 23~29秒插入100W数据 并且蛋疼的是每次都写入一个 RegionServer 且 只在一个 Reg ...
- 手动创建DataTable并添加数据
DataTable dt=new DataTable(); DataColumn dc=dt.Columns.Add("OBJECTID",Type.GetType("S ...
- 利用netstat和tasklist查看PC的端口占用情况 及80端口被占用
经常,我们在启动应用的时候发现系统需要的端口被别的程序占用,如何知道谁占有了我们需要的端口? 1.Windows平台在windows命令行窗口下执行: E:\oracle\ora92\bin>n ...
- Linux下大型容量件的切割与合并
Linux下大型容量件的切割与合并 当前目录下有sp4.exe文件容量129M我用64的U盘把spe.exe考到另一台机器上#split -b 60m sp4.exe-b, --bytes=SIZE ...
- Android之RadioGroup+ViewPager制作的底部导航栏
在日常开发中我们常常会用到类似微信或者QQ的底部导航.实现这样的效果有多种,今天就为大家介绍一种实现简单,可控性好的底部导航的实现方法. 首先创建activity_main.xml布局文件,里面主要由 ...