由生产者消费者模型引出的线程同步问题

基本生产者消费者模型:

代码示例:

数据模型:

/*** Created by IntelliJ IDEA.** @Author: ZhangDong* @Date: 2019/9/9 16:00*/
public class Message {private String tittle;private String content;public String getTittle() {return tittle;}public void setTittle(String tittle) {this.tittle = tittle;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}
}

生产者模型:

/*** Created by IntelliJ IDEA.** @Author: ZhangDong* @Date: 2019/9/9 16:00*/
public class Producer implements Runnable{private Message msg;public Producer(Message msg) {this.msg = msg;}@Overridepublic void run() {for (int i = 0; i < 100; i++) {if (i % 2 == 0){this.msg.setTittle("1.");try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}this.msg.setContent("第一种数据模型");}else {this.msg.setContent("2.");this.msg.setContent("第二种数据模型");}}}
}

消费者模型:

/*** Created by IntelliJ IDEA.** @Author: ZhangDong* @Date: 2019/9/9 16:00*/
public class Consumer implements  Runnable{private Message msg;public Consumer(Message msg) {this.msg = msg;}@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(this.msg.getTittle()+" "+this.msg.getContent());try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}
}

主程序:

/*** Created by IntelliJ IDEA.** @Author: ZhangDong* @Date: 2019/9/9 16:00*/
public class Main {public static void main(String[] args) {Message msg = new Message();//启动生产者模型new Thread(new Producer(msg)).start();//启动消费者模型new Thread(new Consumer(msg)).start();}
}

执行结果:

控制台打印结果令人大跌眼镜,说好的生产一个模型取走一个模型呢?连生产出来的模型都乱了,1号模型对应这2号模型的内容,居然还有null。此时我发现了两个主要问题:

问题一: 数据不同步;

问题二:重复生产和重复取出问题;

问题解决

如果要解决问题,首要解决的就是数据同步的处理问题,如果想要解决数据同步最简单的方法就是使用synchronized关键字定义同步代码块或同步方法,于是这个时候对于同步问题的处理就可以直接在Message类中完成。

解决同步问题:

在进行同步处理的时候肯定需要有一个同步处理的对象,那么此时肯定要将同步操作交由Message来处理。在数据模型Message中修改生产和消费方法,并加上synchronized关键字同步方法。

解决同步问题后的代码示例:

数据模型:

/*** Created by IntelliJ IDEA.** @Author: ZhangDong* @Date: 2019/9/9 16:10*/
public class Message {private String tittle;private String content;public synchronized void set(String tittle, String content) {this.tittle = tittle;try {//模拟生产过程 10毫秒Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}this.content = content;}public synchronized String get() {try {//模拟消费过程 10毫秒Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}return this.tittle + " - " + this.content;}
}

生产者模型:

/*** Created by IntelliJ IDEA.** @Author: ZhangDong* @Date: 2019/9/9 16:10*/
public class Producer implements Runnable {private Message msg;public Producer(Message msg) {this.msg = msg;}@Overridepublic void run() {for (int i = 0; i < 100; i++) {if (i % 2 == 0) {this.msg.set("1.", "第一种数据模型");} else {this.msg.set("2.", "第二种数据模型");}}}
}

消费者模型:

/*** Created by IntelliJ IDEA.** @Author: ZhangDong* @Date: 2019/9/9 16:10*/
public class Consumer implements Runnable {private Message msg;public Consumer(Message msg) {this.msg = msg;}@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(this.msg.get());try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}
}

主程序:

/*** Created by IntelliJ IDEA.** @Author: ZhangDong* @Date: 2019/9/9 16:10*/
public class Main {public static void main(String[] args) {Message msg = new Message();//启动生产者模型new Thread(new Producer(msg)).start();//启动消费者模型new Thread(new Consumer(msg)).start();}
}

执行结果:

根据控制台打印输出可以观察到,刚刚发现的同步问题已经解决了,生产和消费的模型信息都是正确的 1号模型对应第一种数据模型,2号对应第二种数据模型,完全正确,但重复生产重复消费问题依然存在。

接下来我来解决这个重复生产重复消费的问题,典型思路就是,设置一个标记,好比十字路口的红绿灯,绿灯亮时生产者进行生产,消费者等待,红灯亮时消费者进行消费,而生产者停止生产等待消费者消费完成信号灯变为绿色时再进行生产。

终极版本代码示例:

数据模型:

/*** Created by IntelliJ IDEA.** @Author: ZhangDong* @Date: 2019/9/9 16:14*/
public class Message {private String tittle;private String content;/** flag属性控制生产与消费* true:允许生产,不允许消费  false:允许消费,不允许生产* 默认可以生产*/private boolean flag = true;public synchronized void set(String tittle,String content){if (!this.flag){try {super.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.tittle=tittle;try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}this.content=content;//标记为已生产this.flag=false;//唤醒等待线程super.notify();}public synchronized String get() {if (this.flag){try {super.wait();} catch (InterruptedException e) {e.printStackTrace();}}try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}try {return this.tittle+" - "+this.content;}finally {//继续生产this.flag=true;//唤醒等待线程super.notify();}}
}

生产者模型:

/*** Created by IntelliJ IDEA.** @Author: ZhangDong* @Date: 2019/9/9 16:14*/
public class Producer implements Runnable{private Message msg;public Producer(Message msg) {this.msg = msg;}@Overridepublic void run() {for (int i = 0; i < 100; i++) {if (i % 2 == 0){this.msg.set("1.","第一种数据模型");}else {this.msg.set("2.","第二种数据模型");}}}
}

消费者模型:

/*** Created by IntelliJ IDEA.** @Author: ZhangDong* @Date: 2019/9/9 16:14*/
public class Consumer implements  Runnable{private Message msg;public Consumer(Message msg) {this.msg = msg;}@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(this.msg.get());try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}
}

主程序:

/*** Created by IntelliJ IDEA.** @Author: ZhangDong* @Date: 2019/9/9 16:14*/
public class Main {public static void main(String[] args) {Message msg = new Message();//启动生产者模型new Thread(new Producer(msg)).start();//启动消费者模型new Thread(new Consumer(msg)).start();}
}

执行结果:

至此,由生产者消费者模型引出的线程同步问题已经解决,希望能给看到此文章的你一些思路以及解决方法。

生产者消费者代码c语言_由生产者消费者模型引出的线程同步问题相关推荐

  1. 二元置信椭圆r语言_一般加性模型的简介、应用举例及R语言操作

    一般加性模型的简介.应用及R语言操作举例前文在"平滑回归举例"中,提到当未知自变量和响应变量间的关系,难以选择合适的参数模型描述二者间的响应状态,或者期望探索二者可能的响应曲线形式 ...

  2. windows进程生产者消费者代码c语言,生产者消费者问题---C语言实现

    生产者消费者问题(Producer-consumer problem) 是一个多线程同步问题的经典案例. 生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程.与此同时,消费者也在缓冲区消耗 ...

  3. 表白代码c语言_这段代码怎么啦?居然瞬间引起了所有程序员网友的注意!

    不知从何时开始,被黑了十几年的「理工男」得到了释放,人们开始把视线聚焦在了一个群体上,那就是「程序员」!比如,热播的电视大剧<欢乐颂2>里,「直男处女情结」引起了整个互联网热议,众网友纷纷 ...

  4. 计算密码子频率的代码R语言_科学网—R语言终止密码子统计 - 熊荣川的博文

    熊荣川 六盘水师范学院生物信息学实验室 #R语言终止密码子统计 setwd("**") infile = "protein1.fasta" outname = ...

  5. 计算密码子频率的代码R语言_密码子使用频率表

    密码子使用频率表 密码子使用频率表 在密码子使用频率表工具中,包含了大肠杆菌.酵母菌(巴斯德毕赤酵母与酿酒酵母).昆虫(草地贪夜蛾)和哺乳动物细胞(人类HEK细胞与黑线仓鼠CHO细胞以及小鼠NSO细胞 ...

  6. mq多个消费者消费一个消息_一个普通消费者的米家产品使用感受

    受疫情影响,学校开学时间再次延后,这段时间宅在家对所购买的小米生态产品使用频率增加很多,所以就来写写个人使用感受吧,最近这些年差不够购买了40多件小米产品,在此抛开手机不谈,因为已经很久不用小米手机了 ...

  7. covariance matrix r语言_时间序列分析|ARIMAX模型分步骤详解和R中实践

    这是关于时间序列的第N篇文章,本文将介绍ARIMAX模型,简单来说就是在ARIMA的基础上增加一个外生变量.ARIMAX和ARIMA相比在理论上没有太多新的内容,所以本文直接介绍在R里怎么一步一步跑A ...

  8. Qt之线程同步(生产者消费者模式 - QSemaphore)

     简述 生产者将数据写入缓冲区,直到它到达缓冲区的末尾,此时,它将从开始位置重新启动,覆盖现有数据.消费者线程读取数据并将其写入标准错误. Semaphore(信号量) 比 mutex(互斥量)有 ...

  9. 生产者消费者代码_生产者消费者模型:Kotlin 多线程读写文件实例

    计算机科学中的所有问题,都可以通过添加一个间接层来解决. 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题. 生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产 ...

最新文章

  1. YTU 1495 蛇行矩阵 YTU 1607 字符棱形YTU 1959 图案打印YTU 2016 打印金字塔
  2. GRE核心词汇助记与精练-List9切分、部分
  3. CMOS与BIOS的区别
  4. 怎么使用java官方demo?
  5. IE6 CSS bug: position:relative元素被overflow:auto/scroll元素包含
  6. posix thread条件变量
  7. 在 Microsoft word中插入代码
  8. C语言零碎知识点之输入字符数组
  9. 在计算机领域中 媒体是,在计算机中,媒体是指什么
  10. 如何查看一篇论文是否被SCI检索
  11. 多线程与并发系列之CompletableFuture
  12. 数据挖掘项目——Airbnb 新用户的民宿预定结果预测
  13. java入门基础(四)
  14. 转载:毕业半年在富士康的经历
  15. 5分钟介绍各种类型的人工智能技术
  16. Unity3d实现扭动挤压浏览效果
  17. 如何评价python知乎_如何看待当下许多人盲目追风Python
  18. 使用 ALT 键输入特殊符号
  19. 博图SCL_递归算法的应用
  20. Jquery.form自动提交表单上传图片

热门文章

  1. DispatcherServlet详解
  2. Maven知识- repositories
  3. android中setText不能传int值
  4. pyhton链式赋值在可变类型/不可变类型上的区别以及其本质
  5. 阿里云服务器报 Liunx异常文件下载处理办法
  6. 【转】Retrofit
  7. BTREE与其它索引的优缺点对比
  8. js替换字符中的斜杠反斜杠
  9. 学生管理系统(简易)7/26
  10. PDI的steps:(5:Add XML)