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 线程并发(生产者、消费者模式)
线程并发协作(生产者/消费者模式) 多线程环境下,我们经常需要多个线程的并发和协作.这个时候,就需要了解一个重要的多线程并发协作模型“生产者/消费者模式”. Ø 什么是生产者? 生产者指的是负责生产数 ...
随机推荐
- wap上传图片跨域发送post请求
wap和接口交互是跨域请求,一般只能通过Jsonp来进行数据的吞吐,然而jsonp只是GET请求,不能发送post请求,所以会对项目需求有所限制. 需求:wap跨域通过接口上传图片. 条件:接口是C# ...
- ListView 实现多选/单选
http://blog.csdn.net/ljfbest/article/details/40685327 ListView自身带了单选.多选模式,可通过listview.setChoiceMode来 ...
- MVC中使用jquery的浏览器缓存问题
jquery在浏览器ajax调用的时候,对缓存提供了很好的支持,POST方式不能被缓存,使用POST的原因,明确了数据不能被缓存,或者避免JSON攻击(JSON返回数据的时候可以被入侵) jquery ...
- Ext.Net学习笔记12:Ext.Net GridPanel Filter用法
Ext.Net学习笔记12:Ext.Net GridPanel Filter用法 Ext.Net GridPanel的用法在上一篇中已经介绍过,这篇笔记讲介绍Filter的用法. Filter是用来过 ...
- objective-c在Xcode中@property相关参数的解释
objective-c在其对象拥有成员变量时,我们为了保持代码的封装,会将成员变量设置为@protected,并为成员变量编写setter和getter方法. 如: @interface Person ...
- Mysql笔记【3】-SQL约束
SQL 约束 约束用于限制加入表的数据的类型. 可以在创建表时规定约束(通过 CREATE TABLE 语句),或者在表创建之后也可以(通过 ALTER TABLE 语句). 我们将主要探讨以下几种约 ...
- 10.21_Nutz批量插入顺序,POI,wiki持续关注,POI,SSH,数据库优先
(1)Nutz,dao的批量插入会关注顺序吗? http://www.douban.com/group/topic/64322582/ (2)工作需要优先!!! POI,SSH,数据库管理及plsq ...
- 服务器卡死,重启报错: INFO: task blocked for more than 120 seconds
问题:服务器负载很高,但是CPU利用率不高.服务器经常夯住,网站打不开,SSH连接非常不稳定,输入命令夯住. 重启服务器报错: INFO: task blocked for more than 120 ...
- sass中常用mixin
//设置字体大小 @mixin font($s:14px,$h:1.5,$f:microsoft yahei){ font:$s/#{$h} $f; } //参数(方向,大小,颜色),默认:向下,10 ...
- tq --uboot使用
- Nand Flash命令- nand info nand erase nand read[.jffs2] addr off size .jffs代表ECC方式不同 nan ...