java学习之多生产者和多消费者
在上一节当中我们说道了,java多线程当中单个消费者对应单个生产者的关系。这个时候有几个点需要注意一下,第一个就是把if判断flag的语句改成while这样能够避免,比如如果我们这个时候用if的话判断完为真之后,线程就睡过去了,但是当下一次线程notify的时候,这个时候生产者还有消费者,也就是一个锁上面的线程拥有线程苏醒的机会是等同的。这个时候,如果生产者冻结之后,紧接着notify的话这个时候苏醒的还可能是生产者,这是我们不愿意看到的。那我们应该如何来处理呢,这个时候我们就应该把if改成while因为while是个循环,当下一次该线程苏醒的时候还应到回过头来判断,flag标记,这样就避免了生产者自我唤醒的这种情况。
但是现在问题变了,就是这个时候有多个生产者还有多个消费者,我们知道当只有一个生产者还有一个消费者的时候,至少会唤醒其中的一个,那么要是多个生产者还有多个消费者呢,我们可以这样想一下,比如说这个时候有两个生产者A和B,还有两个消费者C和D,此时A生产完了之后,这个时候A就开始唤醒了,假如A唤醒了C这个时候C开始生产消费产品,消费完了之后开始通知其他线程,这个时候假如被唤醒的是D线程,因为flag是假的证明已经没有东西可消费了,这个时候他又冻结。那么这个时候其他线程就都被冻结了,这个时候就形成了死锁现象,如果要避免死锁现象的话,java又为我们提供了一个方法,叫做notifyAll()方法,这个方法的作用在于能够把所有的线程都唤醒,这样就能保证消费者还有生产者至少可以唤醒双方的一个线程,保证程序的正常运行。这样做的一个缺点就是其中还有一个属于己方的线程被唤醒,这样就浪费了资源。于是在jdk更新的时候,就为我们提供了一个新的api能够显式的来操作锁还有唤醒冻结线程,这个线程不再核心lang包当中,这个api在java.util.concurrent.locks这个包当中为我们提供了两个接口,一是Lock接口还有一个是Condition接口。Lock接口扩展的方法有lock()方法还有一个unlock方法,这里需要注意的一点是,无论如何一定要释放锁,这个时候就用到了前面异常所讲到的finally语句,无论如何一定要执行。Lock当中还扩展了一个方法就是newCondition()这个方法,这个方法的作用是给一个锁定义多个消息传递的方式也就是给线程绑定多个监视器,比如说生产者只唤醒消费者的线程,而不唤醒生产者的线程,同理消费者也是如此。同时在Lock当中等待的方法不是wait()方法,唤醒的方法也不是notify()方法,这两个方法分别对应Lock当中的await()方法和signal()方法。
我们综合上面所讲来用代码体现下:
import java.util.concurrent.locks.*;
class KaoYa
{ int num = ; Lock l = new ReentrantLock(); Condition c1 = l.newCondition();
Condition c2 = l.newCondition(); boolean flag; public void produce() throws InterruptedException
{
l.lock(); try{
while(true)
{
while(flag)
c1.await();
System.out.println(Thread.currentThread().getName()+"KaoYa...."+num);
flag = true;
c2.signal();
} //num++; }finally
{
l.unlock();
}
} public void consume() throws InterruptedException
{
l.lock(); try{
while(true)
{
while(!flag)
c2.await();
System.out.println(Thread.currentThread().getName()+"KaoYa------"+num);
num++;
flag = false;
c1.signal();
}
}finally
{ l.unlock(); }
} } class Product implements Runnable
{ KaoYa k;
Product(KaoYa k)
{ this.k = k; } public void run()
{
try{
k.produce();
}catch(InterruptedException e)
{ }
}
} class Consume implements Runnable
{ KaoYa k;
Consume(KaoYa k)
{ this.k = k; } public void run()
{ try{
k.consume();
}catch(InterruptedException e)
{ } } } class LockDemo
{ public static void main(String[] args) { KaoYa k = new KaoYa();
Product p = new Product(k);
Consume c = new Consume(k); Thread t1 = new Thread(p);
Thread t2 = new Thread(p);
Thread t3 = new Thread(c);
Thread t4 = new Thread(c); t1.start();
t2.start();
t3.start();
t4.start(); } }
java学习之多生产者和多消费者的更多相关文章
- 2.5多线程(Java学习笔记)生产者消费者模式
一.什么是生产者消费者模式 生产者生产数据存放在缓冲区,消费者从缓冲区拿出数据处理. 可能大家会问这样有何好处? 1.解耦 由于有了缓冲区,生产者和消费者之间不直接依赖,耦合度降低,便于程序拓展和维护 ...
- java学习多线程之生产者消费者
在java多线程当中还有一种关系需要我们来重点掌握,那就是生产者和消费者的关系.那么什么是生产者,什么是消费者呢?我们可以举个例子来说,有张三.李四负责生产烤鸭,王五.马六负责吃烤鸭,那么前者生产完烤 ...
- Java多线程-并发协作(生产者消费者模型)
对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一样,Hello World!都是最经典的例子. 实际上,准确说应该是“生产者-消费者-仓储”模型,离开了仓 ...
- Java实现PV操作 | 生产者与消费者
导语 在学习操作系统的过程中,PV操作是很重要的一个环节.然而面对书本上枯燥的代码,每一个爱好技术的人总是想能亲自去实现.现在我要推出一个专题,专门讲述如何用Java实现PV操作,让操作系统背后的逻辑 ...
- 使用Java的BlockingQueue实现生产者-消费者
http://tonl.iteye.com/blog/1936391 使用Java的BlockingQueue实现生产者-消费者 博客分类: Java JavaBlockingQueue阻塞队列 B ...
- java 多线程 22 :生产者/消费者模式 进阶 利用await()/signal()实现
java多线程15 :wait()和notify() 的生产者/消费者模式 在这一章已经实现了 wait/notify 生产消费模型 利用await()/signal()实现生产者和消费者模型 一样 ...
- Java并发编程(4)--生产者与消费者模式介绍
一.前言 这种模式在生活是最常见的,那么它的场景是什么样的呢? 下面是我假象的,假设有一个仓库,仓库有一个生产者和一个消费者,消费者过来消费的时候会检测仓库中是否有库存,如果没有了则等待生产,如果有就 ...
- Java多线程设计模式(2)生产者与消费者模式
1 Producer-Consumer Pattern Producer-Consumer Pattern主要就是在生产者与消费者之间建立一个“桥梁参与者”,用来解决生产者线程与消费者线程之间速度的不 ...
- java 线程并发(生产者、消费者模式)
线程并发协作(生产者/消费者模式) 多线程环境下,我们经常需要多个线程的并发和协作.这个时候,就需要了解一个重要的多线程并发协作模型“生产者/消费者模式”. Ø 什么是生产者? 生产者指的是负责生产数 ...
随机推荐
- sharedPreference的奇怪bug
一定要清楚sp的结构,而且要知道是什么类型的.类型不对,会引起很多不知道的bug,比如本来是int类型的值,如果用String的类型去匹配,会让Activity开Activity Thread,不断地 ...
- MVC小系列(一)【制作表格】
在Razor引擎中,对于在表格中进行遍历时,一般会这样写 复制代码 <table border="> @{ ; i < ; i++) { <tr> <td ...
- C#数组按值和按引用传递数组区别
C#中,存储数组之类对象的变量并不是实际存储对象本身,而是存储对象的引用.按值传递数组时,程序将变量传递给方法时,被调用方法接受变量的一个副本,因此在被调用时试图修改数据变量的值时,并不会影响变量的原 ...
- Win7上安装oracle中可能遇到的错误
安装oracle,总是出现一个警告两个错误错误,其描述是:OUI-18001:不支持操作系统’Windows Vista版本6.1’,找了好久,终于找到原因,因为oracle不支持Win7操作系统. ...
- O-C相关-06:对象与对象的关系
对象与对象的关系 1.对象与对象的关系 依赖 关联 组合 常常讨论对象与对象关系时会提供两个属于:内聚性,耦合性 内聚一般指功能上的指向性 耦合一般指关联上的依赖性 2.依赖: 对象之间最弱的一种关联 ...
- 类库探源——System.Configuration 配置信息处理
按照MSDN描述 System.Configuration 命名空间 包含处理配置信息的类型 本篇文章主要两方面的内容 1. 如何使用ConfigurationManager 读取AppSetting ...
- 坑爹CF April Fools Day Contest题解
H - A + B Strikes Back A + B is often used as an example of the easiest problem possible to show som ...
- 【DP_背包专题】 背包九讲
这段时间看了<背包九讲>,在HUST VJUDGE上找到了一个题单,挑选了其中16道题集中做了下,选题全部是HDU上的题,大多是简单题.目前做了点小总结,大概提了下每道题的思路重点部分,希 ...
- 关于Hyper-V虚拟机中的vEthernet虚拟网卡不能联网的问题
Hyper-V虚拟机在我电脑里面已经有一年了,当初是因为windows8系统里面需要装Hyper-V,这样才能不让win8死机,就折腾了一整子,结果碰到vEthernet网卡不能联网,网上相关的资料少 ...
- 以前写过的ajax基础案例(王欢-huanhuan)
//load方法的使用 $('#loadBtn').click(function(){ //responseTxt 包含来自请求的结果数据 //statusTxt 包含请求的状态(" ...