上一节中,通过while和notifyAll解决了多个生产者,消费者对共享资源的访问问题,现在开始升级

但是,仍然有改进之处,主要体现在两点:

1)使用新版本1.5开始后的锁Lock解决,目的将其全部替换实现相同功能

2)由于notifyAll唤醒的是己方和对方线程,我们优化的是只唤醒对方进程

方案1,使用while和notifyAll,synchronized解决多线程访问

代码:

/*
ProducterConsumerDemo解决了只有两个线程共享资源的生产消费问题,主要利用标志位的互斥解决 本程序致力于解决多出现多个生产者,多个消费者的时候,依然能够达到生产一次,消费一次的功能

解决的方法就是:1)在被唤醒之后仍然进行条件判断,去检查要改的数字是否满足条件,如果不满足条件就继续睡眠。把两个方法中的if改为while即可。
当然,此时仍会出现问题,就是所以线程都等待,失去资格
2)需要将notify()改成notifyAll()
*/ class ProducterConsumerDemo2
{
public static void main(String[] args)
{
Resources r =new Resources();
Productor pro =new Productor(r);
Consumer con = new Consumer(r); Thread t1 =new Thread(pro);
Thread t2 =new Thread(pro);//多个生产者
Thread t3 =new Thread(con);
Thread t4 =new Thread(con);//多个消费者
t1.start();
t2.start();
t3.start();
t4.start();
System.out.println("Hello World!");
}
} class Resources
{
private String name;
private int count =1;
private boolean flag =false; public synchronized void set(String name)
{ //1)循环判断
while(flag)
try{this.wait();}catch(Exception e){}
this.name = name+"--"+count++; System.out.println(Thread.currentThread().getName()+"生产者"+this.name);
flag =true;
//2)唤醒所有进程
this.notifyAll(); }
public synchronized void out()
{
//1)循环判断
while(!flag)
try{this.wait();}catch(Exception e){} System.out.println(Thread.currentThread().getName()+" ....消费者...."+this.name);
flag =false;
//2)唤醒所有进程
this.notifyAll(); }
} class Productor implements Runnable
{
private Resources res;
Productor(Resources res){
this.res =res;
}
public void run(){
while(true){
res.set("++商品++");
}
} } class Consumer implements Runnable
{
private Resources res;
Consumer(Resources res){
this.res =res;
}
public void run(){
while(true){
res.out();
}
} }

ProducterConsumerDemo2.java

方案2,解决改进1)的问题

升级版:
使用Lock来替换synchronized,wait,notify,nonifyAll语法和语句的使用
不需要同步,不需要notify

记得需要导包:

java.util.concurrent.locks

主要改动:

自定义锁   ---》 Condition对象 --》signallAll

condition.await()   === try{this.wait();}catch(Exception e){}

synchronized删除,异常抛出,使用finally解锁

 /*

 本程序致力于解决多出现多个生产者,多个消费者的时候,依然能够达到生产一次,消费一次的功能

解决的方法就是:1)在被唤醒之后仍然进行条件判断,去检查要改的数字是否满足条件,如果不满足条件就继续睡眠。把两个方法中的if改为while即可。
当然,此时仍会出现问题,就是所以线程都等待,失去资格
2)需要将notify()改成notifyAll() 升级版:
使用Lock来替换synchronized,wait,notify,nonifyAll语法和语句的使用
不需要同步,不需要notify
*/
import java.util.concurrent.locks.*;
class ProducterConsumerDemo3
{
public static void main(String[] args)
{
Resources r =new Resources();
Productor pro =new Productor(r);
Consumer con = new Consumer(r); Thread t1 =new Thread(pro);
Thread t2 =new Thread(pro);//多个生产者
Thread t3 =new Thread(con);
Thread t4 =new Thread(con);//多个消费者
t1.start();
t2.start();
t3.start();
t4.start();
System.out.println("Hello World!");
}
} class Resources
{
private String name;
private int count =1;
private boolean flag =false;
private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void set(String name) throws InterruptedException
{
lock.lock();
try
{
//1)循环判断
while(flag)
//如果为真,放弃资格
condition.await(); //会抛出异常
this.name = name+"--"+count++; System.out.println(Thread.currentThread().getName()+"生产者"+this.name);
flag =true;
//2)使用condition唤醒所有进程
condition.signalAll(); //如果使用condition.signal()会出现相互等待状况,都失去资格
}
finally
{
lock.unlock();
} }
public void out() throws InterruptedException
{
lock.lock();
try
{
//1)循环判断
while(!flag)
condition.await(); System.out.println(Thread.currentThread().getName()+" ....消费者...."+this.name);
flag =false;
//2)使用condition唤醒所有进程
condition.signalAll();
}
finally //防止当前线程拿到锁后抛异常一直不释放锁
{
lock.unlock();
} }
} class Productor implements Runnable
{
private Resources res;
Productor(Resources res){
this.res =res;
}
public void run(){
while(true){
try
{
res.set("++商品++"); //需要抛出异常
}
catch (InterruptedException e)
{
} }
} } class Consumer implements Runnable
{
private Resources res;
Consumer(Resources res){
this.res =res;
}
public void run(){
while(true){
try
{
res.out(); //需要抛出异常
}
catch (InterruptedException e)
{
} }
} }

此时实现功能和方案1功能一样

方案3,在方案2的基础上解决改进2)的问题

加强升级版:

此版本为最终版,主要在使用锁lock的基础上,加上唤醒对方(不包括己方)进程的优化

 /*

 本程序致力于解决多出现多个生产者,多个消费者的时候,依然能够达到生产一次,消费一次的功能

解决的方法就是:1)在被唤醒之后仍然进行条件判断,去检查要改的数字是否满足条件,如果不满足条件就继续睡眠。把两个方法中的if改为while即可。
当然,此时仍会出现问题,就是所以线程都等待,失去资格
2)需要将notify()改成notifyAll() 升级版:
使用Lock来替换synchronized,wait,notify,nonifyAll语法和语句的使用
不需要同步,不需要notify
------------
加强升级版:
此版本为最终版,主要在使用锁lock的基础上,加上唤醒对方(不包括己方)进程的优化
通过一个锁建立多个condition对象来解决 流程:
生产者拿到锁,执行,判断没有真,继续执行,生产完毕后唤醒消费者来消费 生产者唤醒消费者
消费者拿到锁,执行,判断没有假,继续执行,消费完毕后唤醒生产者继续生产 消费者唤醒生产者

*/
import java.util.concurrent.locks.*;
class ProducterConsumerDemo4
{
public static void main(String[] args)
{
Resources r =new Resources();
Productor pro =new Productor(r);
Consumer con = new Consumer(r); Thread t1 =new Thread(pro);
Thread t2 =new Thread(pro);//多个生产者
Thread t3 =new Thread(con);
Thread t4 =new Thread(con);//多个消费者
t1.start();
t2.start();
t3.start();
t4.start();
System.out.println("Hello World!");
}
} class Resources
{
private String name;
private int count = 1;
private boolean flag =false;
private Lock lock = new ReentrantLock(); private Condition condition_pro = lock.newCondition(); //使用lock建立生产者的condition对象
private Condition condition_con = lock.newCondition(); //使用lock建立消费者的condition对象 public void set(String name) throws InterruptedException
{
lock.lock();
try
{
//1)循环判断
while(flag)
//如果为真,放弃生产者的资格
condition_pro.await(); //会抛出异常
this.name = name+"--"+count++; System.out.println(Thread.currentThread().getName()+"生产者"+this.name);
flag =true;
//2)使用消费condition唤醒进程
condition_con.signal(); //生产者生产完毕后,唤醒消费者的进程(不再是signalAll)
}
finally
{
lock.unlock();
} }
public void out() throws InterruptedException
{
lock.lock();
try
{
//1)循环判断
while(!flag)
//如果为假,放弃消费者的资格
condition_con.await(); System.out.println(Thread.currentThread().getName()+" ....消费者...."+this.name);
flag =false;
//2)使用生产者condition唤醒进程
condition_pro.signal(); //消费者消费完毕后,唤醒生产者的进程
}
finally //防止当前线程拿到锁后抛异常一直不释放锁
{
lock.unlock();
} }
} class Productor implements Runnable
{
private Resources res;
Productor(Resources res){
this.res =res;
}
public void run(){
while(true){
try
{
res.set("++商品++"); //需要抛出异常
}
catch (InterruptedException e)
{
} }
} } class Consumer implements Runnable
{
private Resources res;
Consumer(Resources res){
this.res =res;
}
public void run(){
while(true){
try
{
res.out(); //需要抛出异常
}
catch (InterruptedException e)
{
} }
} }

图示:

java线程之多个生产者消费者2.0的更多相关文章

  1. java线程之多个生产者消费者

    温故一下上一节所学习的生产者消费者代码: 两个线程时: 通过标志位flag的if判断和同步函数互斥较好解决两个线程,一个生产者.一个消费者交替执行的功能 类名:ProducterConsumerDem ...

  2. Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例

    Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例 本文由 TonySpark 翻译自 Javarevisited.转载请参见文章末尾的要求. Java.util.concurr ...

  3. Java多线程之并发协作生产者消费者设计模式

    两个线程一个生产者个一个消费者 需求情景 两个线程,一个负责生产,一个负责消费,生产者生产一个,消费者消费一个 涉及问题 同步问题:如何保证同一资源被多个线程并发访问时的完整性.常用的同步方法是采用标 ...

  4. Java 多线程学习笔记:生产者消费者问题

    前言:最近在学习Java多线程,看到ImportNew网上有网友翻译的一篇文章<阻塞队列实现生产者消费者模式>.在文中,使用的是Java的concurrent包中的阻塞队列来实现.在看完后 ...

  5. java 多线程并发系列之 生产者消费者模式的两种实现

    在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...

  6. java多线程系列15 设计模式 生产者 - 消费者模式

    生产者-消费者 生产者消费者模式是一个非常经典的多线程模式,比如我们用到的Mq就是其中一种具体实现 在该模式中 通常会有2类线程,消费者线程和生产者线程 生产者提交用户请求 消费者负责处理生产者提交的 ...

  7. python进阶:Python进程、线程、队列、生产者/消费者模式、协程

    一.进程和线程的基本理解 1.进程 程序是由指令和数据组成的,编译为二进制格式后在硬盘存储,程序启动的过程是将二进制数据加载进内存,这个启动了的程序就称作进程(可简单理解为进行中的程序).例如打开一个 ...

  8. 【Java并发编程】:生产者—消费者模型

    生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据. 这里实现如下情况的生产--消费模型: 生产者不断交替地生产两组数据“姓 ...

  9. java信号量PV操作 解决生产者-消费者问题

    package test1; /** * 该例子演示生产者和消费者的问题(设只有一个缓存空间.一个消费者和一个生产者) * MySystem类定义了缓冲区个数以及信号量 * @author HYY * ...

随机推荐

  1. Extjs4新特性

    Extjs 4相对于之前的版本作出了重大的修正.其中包括全新的类系统.新平台的引入.API的修整和加强还有新组件的引入(如新的图表和图形组件).Extjs 4提供更快速.更稳定的用户体验,并且让开发人 ...

  2. 内层div的margin-top影响外层div——引出外边距合并Collapsing margins

    内层div的margin-top影响外层div——引出外边距合并Collapsing margins 作者:zccst 今天才算是了解边距合并.正如一位前辈所言,每一个CSS的坑,都让你学到不少知识. ...

  3. S3C2440时钟系统详解

    在讲述系统时钟之前,因为这些设备都是挂靠在系统时钟上的,所以必须先说系统时钟,S3C2440的时钟系统如下 外部时钟源分两种,晶振或者外部频率,由om3-2选择,时钟电路根据两种选择也有两种 我们来分 ...

  4. 【转】进程间通信方式总结(windows 和linux)

    平时看的书很多,了解的也很多,但不喜欢总结,这不昨天面试的时候被问到了进程间通信的方式,因为没有认真总结过,所以昨天答得不是特别好.现在将linux和windows的进程间通信方式好好总结一下.    ...

  5. Unity3D ——强大的跨平台3D游戏开发工具(五)

    第九章 图形用户界面类G.U.I 您在玩很多3D游戏的时候,不知是否注意到在游戏界面中,总有一些图形和文字信息是不随着3D视角的改变而改变的.这也是由于游戏本身的要求而决定的.比如说英雄的生命值,聊天 ...

  6. VMVare 桥接上网

    桥接模式设置小解: 第1步 虚拟机下fedora安装好后,打开VM虚拟机的菜单栏,单击编辑------虚拟网络编辑器,选择“主机虚拟网络 映射”标签,然后把VMnet0 手动选择为你本地的物理网卡(要 ...

  7. .NET Core installation guide

      .NET Core installation guide 1.Download Visual Studio 2015 Make sure you have Visual Studio 2015 U ...

  8. Unity3d学习 基础-关于MonoBehaviour的生命周期

    其实在刚接触Unity3D,会有一个疑问,关于Unity3D游戏运行的初始入口在哪?不像Cocos2dx还有个AppDelegate文件可以去理解.而且在刚开始就接触Unity3D时,看到所有脚本中编 ...

  9. Python3基础 set() 集合 创建集合与特点:自动将重复合并掉 不支持索引

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...

  10. Javascript 查找元素

    DOM定义了多种查找元素的方法,除了我们常用的getElementById(),还有getElementsByTagName()和getElementsByName().使用这几种方法方法我们可以查找 ...