zoukankan      html  css  js  c++  java
  • 生产者—消费者模型

     生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据。

    这里实现如下情况的生产--消费模型:

        生产者不断交替地生产两组数据“姓名--1 --> 内容--1”,“姓名--2--> 内容--2”,消费者不断交替地取得这两组数据,这里的“姓名--1”和“姓名--2”模拟为数据的名称,“内容--1 ”和“内容--2 ”模拟为数据的内容。

      由于本程序中牵扯到线程运行的不确定性,因此可能会出现以下问题:

         1、假设生产者线程刚向数据存储空间添加了数据的名称,还没有加入该信息的内容,程序就切换到了消费者线程,消费者线程将把信息的名称和上一个信息的内容联系在一起;

         2、生产者生产了若干次数据,消费者才开始取数据,或者是,消费者取完一次数据后,还没等生产者放入新的数据,又重复取出了已取过的数据。

         问题1很明显要靠同步来解决,问题2则需要线程间通信,生产者线程放入数据后,通知消费者线程取出数据,消费者线程取出数据后,通知生产者线程生产数据,这里用wait/notify机制来实现。

     详细的实现代码如下:

     1 class Info{ // 定义信息类  
     2     private String name = "name";//定义name属性,为了与下面set的name属性区别开  
     3     private String content = "content" ;// 定义content属性,为了与下面set的content属性区别开  
     4     private boolean flag = true ;   // 设置标志位,初始时先生产  
     5     public synchronized void set(String name,String content){  
     6         while(!flag){  
     7             try{  
     8                 super.wait() ;  
     9             }catch(InterruptedException e){  
    10                 e.printStackTrace() ;  
    11             }  
    12         }  
    13         this.setName(name) ;    // 设置名称  
    14         try{  
    15             Thread.sleep(300) ;  
    16         }catch(InterruptedException e){  
    17             e.printStackTrace() ;  
    18         }  
    19         this.setContent(content) ;  // 设置内容  
    20         flag  = false ; // 改变标志位,表示可以取走  
    21         super.notify();  
    22     }  
    23     public synchronized void get(){  
    24         while(flag){  
    25             try{  
    26                 super.wait() ;  
    27             }catch(InterruptedException e){  
    28                 e.printStackTrace() ;  
    29             }  
    30         }  
    31         try{  
    32             Thread.sleep(300) ;  
    33         }catch(InterruptedException e){  
    34             e.printStackTrace() ;  
    35         }  
    36         System.out.println(this.getName() +   
    37             " --> " + this.getContent()) ;  
    38         flag  = true ;  // 改变标志位,表示可以生产  
    39         super.notify();  
    40     }  
    41     public void setName(String name){  
    42         this.name = name ;  
    43     }  
    44     public void setContent(String content){  
    45         this.content = content ;  
    46     }  
    47     public String getName(){  
    48         return this.name ;  
    49     }  
    50     public String getContent(){  
    51         return this.content ;  
    52     }  
    53 }  
    54 class Producer implements Runnable{ // 通过Runnable实现多线程  
    55     private Info info = null ;      // 保存Info引用  
    56     public Producer(Info info){  
    57         this.info = info ;  
    58     }  
    59     public void run(){  
    60         boolean flag = true ;   // 定义标记位  
    61         for(int i=0;i<10;i++){  
    62             if(flag){  
    63                 this.info.set("姓名--1","内容--1") ;    // 设置名称  
    64                 flag = false ;  
    65             }else{  
    66                 this.info.set("姓名--2","内容--2") ;    // 设置名称  
    67                 flag = true ;  
    68             }  
    69         }  
    70     }  
    71 }  
    72 class Consumer implements Runnable{  
    73     private Info info = null ;  
    74     public Consumer(Info info){  
    75         this.info = info ;  
    76     }  
    77     public void run(){  
    78         for(int i=0;i<10;i++){  
    79             this.info.get() ;  
    80         }  
    81     }  
    82 }  
    83 public class ThreadCaseDemo03{  
    84     public static void main(String args[]){  
    85         Info info = new Info(); // 实例化Info对象  
    86         Producer pro = new Producer(info) ; // 生产者  
    87         Consumer con = new Consumer(info) ; // 消费者  
    88         new Thread(pro).start() ;  
    89         //启动了生产者线程后,再启动消费者线程  
    90         try{  
    91             Thread.sleep(500) ;  
    92         }catch(InterruptedException e){  
    93             e.printStackTrace() ;  
    94         }  
    95   
    96         new Thread(con).start() ;  
    97     }  
    98 }  

    执行结果如下:

     另外,在run方法中,二者循环的次数要相同,否则,当一方的循环结束时,另一方的循环依然继续,它会阻塞在wait()方法处,而等不到对方的notify通知

  • 相关阅读:
    JS站点
    1011 World Cup Betting (20分)
    1007 Maximum Subsequence Sum (25分)(动态规划DP)
    1006 Sign In and Sign Out (25分)
    1005 Spell It Right (20分)
    1004 Counting Leaves (30分)(DFS)
    1003 Emergency (25分)(Dijkstra算法)
    1002 A+B for Polynomials (25分)
    1001 A+B Format (20分)
    canvas
  • 原文地址:https://www.cnblogs.com/lt132024/p/6442904.html
Copyright © 2011-2022 走看看