• java线程之多个生产者消费者2.0


    上一节中,通过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 /*
      2 
      3 本程序致力于解决多出现多个生产者,多个消费者的时候,依然能够达到生产一次,消费一次的功能
      4   5 解决的方法就是:1)在被唤醒之后仍然进行条件判断,去检查要改的数字是否满足条件,如果不满足条件就继续睡眠。把两个方法中的if改为while即可。
      6 当然,此时仍会出现问题,就是所以线程都等待,失去资格
      7                 2)需要将notify()改成notifyAll()
      8 
      9 升级版:
     10 使用Lock来替换synchronized,wait,notify,nonifyAll语法和语句的使用
     11 不需要同步,不需要notify
     12 */
     13 import java.util.concurrent.locks.*;
     14 class  ProducterConsumerDemo3
     15 {
     16     public static void main(String[] args) 
     17     {
     18         Resources  r =new Resources();
     19         Productor  pro =new Productor(r);
     20         Consumer   con = new Consumer(r);
     21         
     22         Thread t1 =new Thread(pro);
     23         Thread t2 =new Thread(pro);//多个生产者
     24         Thread t3 =new Thread(con);
     25         Thread t4 =new Thread(con);//多个消费者
     26         t1.start();
     27         t2.start();
     28         t3.start();
     29         t4.start();
     30         System.out.println("Hello World!");
     31     }
     32 }
     33 
     34 class Resources
     35 {
     36     private String name;
     37     private int count =1;
     38     private boolean flag =false;
     39     private Lock lock = new ReentrantLock();
     40 
     41     private Condition condition = lock.newCondition();
     42 
     43     public  void set(String name) throws InterruptedException
     44     {  
     45         lock.lock();
     46         try
     47         {
     48             //1)循环判断
     49            while(flag)
     50                //如果为真,放弃资格
     51                condition.await(); //会抛出异常
     52            this.name = name+"--"+count++;
     53 
     54            System.out.println(Thread.currentThread().getName()+"生产者"+this.name);
     55            flag =true;
     56            //2)使用condition唤醒所有进程
     57            condition.signalAll(); //如果使用condition.signal()会出现相互等待状况,都失去资格
     58         }
     59         finally 
     60         {
     61             lock.unlock();
     62         }
     63         
     64        
     65     }
     66     public  void out() throws InterruptedException
     67     {
     68         lock.lock();
     69         try
     70         {
     71            //1)循环判断
     72            while(!flag)
     73                condition.await();
     74            
     75            System.out.println(Thread.currentThread().getName()+" ....消费者...."+this.name);
     76            flag =false;
     77            //2)使用condition唤醒所有进程
     78            condition.signalAll();
     79         }
     80         finally    //防止当前线程拿到锁后抛异常一直不释放锁
     81         {
     82             lock.unlock();
     83         }
     84       
     85 
     86     }
     87 }
     88 
     89 class Productor implements Runnable
     90 {
     91     private Resources res;
     92     Productor(Resources res){
     93         this.res =res;
     94     }
     95     public void run(){
     96         while(true){
     97             try
     98             {
     99                 res.set("++商品++"); //需要抛出异常
    100             }
    101             catch (InterruptedException e)
    102             {
    103             }
    104             
    105         }
    106     }
    107 
    108 }
    109 
    110 class Consumer  implements Runnable
    111 {
    112     private Resources res;
    113     Consumer(Resources res){
    114         this.res =res;
    115     }
    116     public void run(){
    117         while(true){
    118              try
    119             {
    120                 res.out(); //需要抛出异常
    121             }
    122             catch (InterruptedException e)
    123             {
    124             }
    125             
    126         }
    127     }
    128 
    129 }

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

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

    加强升级版:

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

      1 /*
      2 
      3 本程序致力于解决多出现多个生产者,多个消费者的时候,依然能够达到生产一次,消费一次的功能
      4   5 解决的方法就是:1)在被唤醒之后仍然进行条件判断,去检查要改的数字是否满足条件,如果不满足条件就继续睡眠。把两个方法中的if改为while即可。
      6 当然,此时仍会出现问题,就是所以线程都等待,失去资格
      7                 2)需要将notify()改成notifyAll()
      8 
      9 升级版:
     10 使用Lock来替换synchronized,wait,notify,nonifyAll语法和语句的使用
     11 不需要同步,不需要notify
     12 ------------
     13 加强升级版:
     14 此版本为最终版,主要在使用锁lock的基础上,加上唤醒对方(不包括己方)进程的优化
     15 通过一个锁建立多个condition对象来解决
     16 
     17 流程:
     18 生产者拿到锁,执行,判断没有真,继续执行,生产完毕后唤醒消费者来消费    生产者唤醒消费者
     19 消费者拿到锁,执行,判断没有假,继续执行,消费完毕后唤醒生产者继续生产   消费者唤醒生产者
     20 
     21 */
     22 import java.util.concurrent.locks.*;
     23 class  ProducterConsumerDemo4
     24 {
     25     public static void main(String[] args) 
     26     {
     27         Resources  r =new Resources();
     28         Productor  pro =new Productor(r);
     29         Consumer   con = new Consumer(r);
     30         
     31         Thread t1 =new Thread(pro);
     32         Thread t2 =new Thread(pro);//多个生产者
     33         Thread t3 =new Thread(con);
     34         Thread t4 =new Thread(con);//多个消费者
     35         t1.start();
     36         t2.start();
     37         t3.start();
     38         t4.start();
     39         System.out.println("Hello World!");
     40     }
     41 }
     42 
     43 class Resources
     44 {
     45     private String name;
     46     private int count = 1;
     47     private boolean flag =false;
     48     private Lock lock = new ReentrantLock();
     49 
     50     private Condition condition_pro = lock.newCondition(); //使用lock建立生产者的condition对象
     51     private Condition condition_con = lock.newCondition(); //使用lock建立消费者的condition对象
     52 
     53     public  void set(String name) throws InterruptedException
     54     {  
     55         lock.lock();
     56         try
     57         {
     58             //1)循环判断
     59            while(flag)
     60                //如果为真,放弃生产者的资格
     61                condition_pro.await(); //会抛出异常
     62            this.name = name+"--"+count++;
     63 
     64            System.out.println(Thread.currentThread().getName()+"生产者"+this.name);
     65            flag =true;
     66            //2)使用消费condition唤醒进程
     67            condition_con.signal(); //生产者生产完毕后,唤醒消费者的进程(不再是signalAll)
     68         }
     69         finally 
     70         {
     71             lock.unlock();
     72         }
     73         
     74        
     75     }
     76     public  void out() throws InterruptedException
     77     {
     78         lock.lock();
     79         try
     80         {
     81            //1)循环判断
     82            while(!flag)
     83                //如果为假,放弃消费者的资格
     84                condition_con.await();
     85            
     86            System.out.println(Thread.currentThread().getName()+" ....消费者...."+this.name);
     87            flag =false;
     88            //2)使用生产者condition唤醒进程
     89            condition_pro.signal(); //消费者消费完毕后,唤醒生产者的进程
     90         }
     91         finally    //防止当前线程拿到锁后抛异常一直不释放锁
     92         {
     93             lock.unlock();
     94         }
     95       
     96 
     97     }
     98 }
     99 
    100 class Productor implements Runnable
    101 {
    102     private Resources res;
    103     Productor(Resources res){
    104         this.res =res;
    105     }
    106     public void run(){
    107         while(true){
    108             try
    109             {
    110                 res.set("++商品++"); //需要抛出异常
    111             }
    112             catch (InterruptedException e)
    113             {
    114             }
    115             
    116         }
    117     }
    118 
    119 }
    120 
    121 class Consumer  implements Runnable
    122 {
    123     private Resources res;
    124     Consumer(Resources res){
    125         this.res =res;
    126     }
    127     public void run(){
    128         while(true){
    129              try
    130             {
    131                 res.out(); //需要抛出异常
    132             }
    133             catch (InterruptedException e)
    134             {
    135             }
    136             
    137         }
    138     }
    139 
    140 }

    图示:

  • 相关阅读:
    HttpWebRequest请求超时的解决方案!
    HttpWebRequest常用问题!
    System.IO 的三个抽象类
    枚举
    IINQ 的链接
    怎么样将sql server数据库中的结构导入到powerdesign中
    System.IO的三个静态类
    System.IO TextReader的二个子类
    学习序列化
    LookAndFeel枚举说明
  • 原文地址:https://www.cnblogs.com/shuqingstudy/p/5057787.html
Copyright © 2020-2023  润新知