java线程之多个生产者消费者2.0
2015-12-18 17:46
459 查看
上一节中,通过while和notifyAll解决了多个生产者,消费者对共享资源的访问问题,现在开始升级
但是,仍然有改进之处,主要体现在两点:
1)使用新版本1.5开始后的锁Lock解决,目的将其全部替换实现相同功能
2)由于notifyAll唤醒的是己方和对方线程,我们优化的是只唤醒对方进程
方案1,使用while和notifyAll,synchronized解决多线程访问
代码:
ProducterConsumerDemo2.java
方案2,解决改进1)的问题
升级版:
使用Lock来替换synchronized,wait,notify,nonifyAll语法和语句的使用
不需要同步,不需要notify
记得需要导包:
自定义锁 ---》 Condition对象 --》signallAll
condition.await() === try{this.wait();}catch(Exception e){}
synchronized删除,异常抛出,使用finally解锁
此时实现功能和方案1功能一样
方案3,在方案2的基础上解决改进2)的问题
加强升级版:
此版本为最终版,主要在使用锁lock的基础上,加上唤醒对方(不包括己方)进程的优化
图示:
但是,仍然有改进之处,主要体现在两点:
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) { } } } }
图示:
![](http://images2015.cnblogs.com/blog/756212/201512/756212-20151218174512646-1621243330.png)
相关文章推荐
- SpringMvc easyUi Mybatis Spring , demo简单的例子
- Java二维码工具类(使用zxing实现,可支持logo)
- Java提高篇(三六)-----java集合细节(二):asList的缺陷
- Java :Annotation(注释)
- 组合(从长度为n的字符串中取m个字符)---java两种实现方法
- Java提高配(三七)—–Java集合细节(三):subList的缺陷
- 【JavaWeb】 ServletContext以及讲解Servlet转发
- struts2 注解方式返回json
- java提高篇(十六)-----异常(一)
- 判断某年是否是闰年 in Java
- java提高篇(十四)-----关键字final
- java提高篇(十三)-----字符串
- 解决因生成javadoc失败导致Maven打包失败问题
- java提高篇(十二)-----equals()
- java提高篇(十一)-----代码块
- java提高篇(十)-----强制类型转换
- java提高篇(九)-----详解匿名内部类
- java提高篇(八)-----实现多重继承
- java编程中Properties类的具体作用和使用
- volatile、synchronized、lock学习笔记