博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
生产者—消费者模型
阅读量:6272 次
发布时间:2019-06-22

本文共 3745 字,大约阅读时间需要 12 分钟。

hot3.png

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

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

    生产者不断交替地生产两组数据“姓名--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通知

转载于:https://my.oschina.net/architectliuyuanyuan/blog/1615697

你可能感兴趣的文章
Lua
查看>>
Mysql备份系列(3)--innobackupex备份mysql大数据(全量+增量)操作记录
查看>>
postgresql 获取刚刚插入的数据主键id
查看>>
C# Activex开发、打包、签名、发布 C# Activex开发、打包、签名、发布 [转]
查看>>
05-Vue入门系列之Vue实例详解与生命周期
查看>>
验证码展示
查看>>
浅谈大型web系统架构
查看>>
淘宝大秒系统设计详解
查看>>
linux如何修改登录用户密码
查看>>
Kali Linux 2017中Scapy运行bug解决
查看>>
Python监控进程性能数据并画图保存为PDF文档
查看>>
Android属性动画完全解析(下),Interpolator和ViewPropertyAnimator的用法
查看>>
Mac OS 10.10.3下Apache + mod_wsgi配置【一】
查看>>
Hibernate基于注解的双向one-to-many映射关系的实现
查看>>
算法竞赛入门经典 例题 3-2 蛇形填数
查看>>
remove-duplicates-from-sorted-list I&II——去除链表中重复项
查看>>
c++ 网络库
查看>>
Linux 格式化扩展分区(Extended)
查看>>
linux echo命令
查看>>
nginx 内置变量大全(转)
查看>>