热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JUC:4_1并发协作模型:生产者消费者模型

JUC:4_1并发协作模型:生产者消费者模型线程通信问题synchronized版本的管程法Lock版本的管程法线程通信问题线程之间的通信问题

JUC:4_1并发协作模型:生产者消费者模型

  • 线程通信问题
  • synchronized版本的管程法
  • Lock版本的管程法


线程通信问题

线程之间的通信问题,就是生产者和消费者问题,也就是如何做到多个线程交替执行。

并发协作模型:生产者消费者模型 解决方式1.管程法
并发协作模型:生产者消费者模型 解决方式2.信号灯法

上面两个是基于synchronized、wait、notify来去做的,现在改为Lock去做。

synchronized版本的管程法

/*** 并发协作模型"生产者/消费者模式"* 线程之间的通信问题,就是生产者和消费者问题,也就是如何做到多个线程交替执行* 比如一个线程++A* 一个线程--A* 需要先放入再执行另一个操作*/
public class TestPC {public static void main(String[] args) {SyncContainer container &#61; new SyncContainer();//生产者new Thread(() -> {for (int i &#61; 0; i < 100; i&#43;&#43;) {container.push(new Product(i));System.out.println("将产品放入缓冲区&#xff1a;" &#43; i);}}).start();//消费者new Thread(() -> {for (int i &#61; 0; i < 100; i&#43;&#43;) {System.out.println("消费产品" &#43; container.pop().getPid());}}).start();}
}//产品
class Product {private int pid;//产品编号public int getPid() {return pid;}public void setPid(int pid) {this.pid &#61; pid;}public Product(int pid) {this.pid &#61; pid;}
}//缓冲区
class SyncContainer {//容器大小&#xff0c;默认容量指定10private static final int DEFAULT_CAPACITY &#61; 10;Product[] products &#61; new Product[DEFAULT_CAPACITY];//容器计数器int count &#61; 0;//生产者放产品public synchronized void push(Product product) {if (count &#61;&#61; products.length) {//容器已满&#xff0c;需要等待消费//通知消费者消费&#xff0c;生产者等待try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//容器不满&#xff0c;可以放产品products[count] &#61; product;count&#43;&#43;;//通知消费者消费&#xff0c;这里用notifyAll和notify结果都是一样的&#xff0c;因为不会同时阻塞this.notifyAll();}//消费者消费产品public synchronized Product pop() {//判断容器有无产品&#xff0c;无则阻塞if (count &#61;&#61; 0) {//等待生产者生产&#xff0c;消费者等待try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//可以消费&#xff0c;这里主要&#xff1a;count--必须在前&#xff0c;因为生产者生产之后count&#43;&#43;会&#43;1count--;Product product &#61; products[count];//通知生产者生产&#xff0c;这里用notifyAll和notify结果都是一样的&#xff0c;因为不会同时阻塞this.notify();return product;}
}

输出&#xff1a;

将产品放入缓冲区&#xff1a;0
将产品放入缓冲区&#xff1a;1
将产品放入缓冲区&#xff1a;2
将产品放入缓冲区&#xff1a;3
将产品放入缓冲区&#xff1a;4
将产品放入缓冲区&#xff1a;5
将产品放入缓冲区&#xff1a;6
将产品放入缓冲区&#xff1a;7
将产品放入缓冲区&#xff1a;8
将产品放入缓冲区&#xff1a;9
消费产品9
将产品放入缓冲区&#xff1a;10
消费产品10
将产品放入缓冲区&#xff1a;11
将产品放入缓冲区&#xff1a;12
消费产品11
消费产品12
将产品放入缓冲区&#xff1a;13
消费产品13
将产品放入缓冲区&#xff1a;14
消费产品14
将产品放入缓冲区&#xff1a;15
消费产品15
将产品放入缓冲区&#xff1a;16
将产品放入缓冲区&#xff1a;17
消费产品16
消费产品17
将产品放入缓冲区&#xff1a;18
将产品放入缓冲区&#xff1a;19
消费产品18
消费产品19
将产品放入缓冲区&#xff1a;20
将产品放入缓冲区&#xff1a;21
消费产品20
消费产品21
将产品放入缓冲区&#xff1a;22
消费产品22
将产品放入缓冲区&#xff1a;23
消费产品23
消费产品24
将产品放入缓冲区&#xff1a;24
消费产品8
将产品放入缓冲区&#xff1a;25
消费产品25
将产品放入缓冲区&#xff1a;26
消费产品26
将产品放入缓冲区&#xff1a;27
将产品放入缓冲区&#xff1a;28
消费产品27
将产品放入缓冲区&#xff1a;29
消费产品29
将产品放入缓冲区&#xff1a;30
消费产品30
将产品放入缓冲区&#xff1a;31
消费产品31
将产品放入缓冲区&#xff1a;32
消费产品32
将产品放入缓冲区&#xff1a;33
消费产品33
将产品放入缓冲区&#xff1a;34
消费产品34
将产品放入缓冲区&#xff1a;35
消费产品35
将产品放入缓冲区&#xff1a;36
消费产品36
将产品放入缓冲区&#xff1a;37
消费产品37
将产品放入缓冲区&#xff1a;38
消费产品38
将产品放入缓冲区&#xff1a;39
消费产品39
将产品放入缓冲区&#xff1a;40
消费产品40
将产品放入缓冲区&#xff1a;41
消费产品41
将产品放入缓冲区&#xff1a;42
消费产品42
将产品放入缓冲区&#xff1a;43
消费产品43
将产品放入缓冲区&#xff1a;44
消费产品44
将产品放入缓冲区&#xff1a;45
消费产品45
将产品放入缓冲区&#xff1a;46
消费产品46
将产品放入缓冲区&#xff1a;47
消费产品47
将产品放入缓冲区&#xff1a;48
消费产品48
将产品放入缓冲区&#xff1a;49
消费产品49
将产品放入缓冲区&#xff1a;50
消费产品50
将产品放入缓冲区&#xff1a;51
消费产品51
将产品放入缓冲区&#xff1a;52
消费产品52
将产品放入缓冲区&#xff1a;53
消费产品53
将产品放入缓冲区&#xff1a;54
消费产品54
将产品放入缓冲区&#xff1a;55
消费产品55
将产品放入缓冲区&#xff1a;56
消费产品56
将产品放入缓冲区&#xff1a;57
消费产品57
将产品放入缓冲区&#xff1a;58
消费产品58
将产品放入缓冲区&#xff1a;59
消费产品59
将产品放入缓冲区&#xff1a;60
消费产品60
将产品放入缓冲区&#xff1a;61
消费产品61
将产品放入缓冲区&#xff1a;62
消费产品62
将产品放入缓冲区&#xff1a;63
将产品放入缓冲区&#xff1a;64
消费产品63
消费产品64
消费产品65
将产品放入缓冲区&#xff1a;65
消费产品28
将产品放入缓冲区&#xff1a;66
消费产品66
将产品放入缓冲区&#xff1a;67
消费产品67
将产品放入缓冲区&#xff1a;68
消费产品68
将产品放入缓冲区&#xff1a;69
消费产品69
将产品放入缓冲区&#xff1a;70
消费产品70
将产品放入缓冲区&#xff1a;71
消费产品71
将产品放入缓冲区&#xff1a;72
消费产品72
将产品放入缓冲区&#xff1a;73
消费产品73
将产品放入缓冲区&#xff1a;74
消费产品74
将产品放入缓冲区&#xff1a;75
将产品放入缓冲区&#xff1a;76
消费产品75
将产品放入缓冲区&#xff1a;77
消费产品77
将产品放入缓冲区&#xff1a;78
将产品放入缓冲区&#xff1a;79
消费产品78
消费产品79
将产品放入缓冲区&#xff1a;80
将产品放入缓冲区&#xff1a;81
消费产品80
消费产品81
将产品放入缓冲区&#xff1a;82
消费产品82
将产品放入缓冲区&#xff1a;83
消费产品83
将产品放入缓冲区&#xff1a;84
消费产品84
将产品放入缓冲区&#xff1a;85
将产品放入缓冲区&#xff1a;86
消费产品85
消费产品86
将产品放入缓冲区&#xff1a;87
消费产品87
将产品放入缓冲区&#xff1a;88
消费产品88
将产品放入缓冲区&#xff1a;89
消费产品89
消费产品90
将产品放入缓冲区&#xff1a;90
消费产品76
将产品放入缓冲区&#xff1a;91
消费产品91
将产品放入缓冲区&#xff1a;92
消费产品92
将产品放入缓冲区&#xff1a;93
消费产品93
将产品放入缓冲区&#xff1a;94
消费产品94
将产品放入缓冲区&#xff1a;95
消费产品95
将产品放入缓冲区&#xff1a;96
消费产品96
将产品放入缓冲区&#xff1a;97
消费产品97
将产品放入缓冲区&#xff1a;98
消费产品98
将产品放入缓冲区&#xff1a;99
消费产品99
消费产品7
消费产品6
消费产品5
消费产品4
消费产品3
消费产品2
消费产品1
消费产品0

Lock版本的管程法

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** 并发协作模型"生产者/消费者模式"* 线程之间的通信问题&#xff0c;就是生产者和消费者问题&#xff0c;也就是如何做到多个线程交替执行* 比如一个线程&#43;&#43;A* 一个线程--A* 需要先放入再执行另一个操作*/
public class TestPC2 {public static void main(String[] args) {SyncContainer container &#61; new SyncContainer();//生产者new Thread(() -> {for (int i &#61; 0; i < 100; i&#43;&#43;) {container.push(new Product(i));System.out.println("将产品放入缓冲区&#xff1a;" &#43; i);}}).start();//消费者new Thread(() -> {for (int i &#61; 0; i < 100; i&#43;&#43;) {System.out.println("消费产品:" &#43; container.pop().getPid());}}).start();}
}//产品
class Product2 {private int pid;//产品编号public int getPid() {return pid;}public void setPid(int pid) {this.pid &#61; pid;}public Product2(int pid) {this.pid &#61; pid;}
}//缓冲区
class SyncContainer2 {//容器大小&#xff0c;默认容量指定10private static final int DEFAULT_CAPACITY &#61; 10;Product2[] products &#61; new Product2[DEFAULT_CAPACITY];final Lock lock &#61; new ReentrantLock();//默认非公平锁&#xff0c;可以添加true类型设置为公平锁final Condition productor &#61; lock.newCondition();final Condition consumer &#61; lock.newCondition();//容器计数器int count &#61; 0;//生产者放产品public void push(Product2 product) {lock.lock();//加锁//lock.tryLock();//尝试获取锁&#xff0c;这个就是和synchronized区别&#xff0c;不会傻傻的一直等待try {if (count > products.length) {////容器已满&#xff0c;需要等待消费//通知消费者消费&#xff0c;生产者等待try {productor.await();} catch (InterruptedException e) {e.printStackTrace();}}//容器不满&#xff0c;可以放产品products[count] &#61; product;count&#43;&#43;;//通知消费者消费&#xff0c;这里与sychonized的唤醒时用的notifyAll和notify不同&#xff0c;用signalconsumer.signal();} finally {lock.unlock();//解锁}}//消费者消费产品public Product2 pop() {lock.lock();//加锁Product2 product;try {//lock.tryLock();//尝试获取锁&#xff0c;这个就是和synchronized区别&#xff0c;不会傻傻的一直等待//判断容器有无产品&#xff0c;无则阻塞if (count &#61;&#61; 0) {//等待生产者生产&#xff0c;消费者等待try {consumer.wait();} catch (InterruptedException e) {e.printStackTrace();}}//可以消费&#xff0c;这里主要&#xff1a;count--必须在前&#xff0c;因为生产者生产之后count&#43;&#43;会&#43;1count--;product &#61; products[count];productor.signal();} finally {lock.unlock();}return product;}
}


推荐阅读
  • 本次发布的Qt音乐播放器2.0版本在用户界面方面进行了细致优化,提升了整体的视觉效果和用户体验。尽管核心功能与1.0版本保持一致,但界面的改进使得操作更加直观便捷,为用户带来了更为流畅的使用体验。此外,我们还对部分细节进行了微调,以确保软件的稳定性和性能得到进一步提升。 ... [详细]
  • Java集合框架特性详解与开发实践笔记
    Java集合框架特性详解与开发实践笔记 ... [详细]
  • JDK 1.8引入了多项并发新特性,显著提升了编程效率。本文重点探讨了LongAdder和StampedLock的特性和应用场景。此外,还介绍了在多线程环境中发生死锁时,如何通过jps命令进行诊断和排查,提供了详细的步骤和示例。这些改进不仅增强了系统的性能,还简化了开发者的调试工作。 ... [详细]
  • 题目:图像处理(HDU1828,计算周长并集,利用线段树与离散化技术进行扫描) ... [详细]
  • 在探讨C语言编程文本编辑器的最佳选择与专业推荐时,本文将引导读者构建一个基础的文本编辑器程序。该程序不仅能够打开并显示文本文件的内容及其路径,还集成了菜单和工具栏功能,为用户提供更加便捷的操作体验。通过本案例的学习,读者可以深入了解文本编辑器的核心实现机制。 ... [详细]
  • 【并发编程】全面解析 Java 内存模型,一篇文章带你彻底掌握
    本文深入解析了 Java 内存模型(JMM),从基础概念到高级特性进行全面讲解,帮助读者彻底掌握 JMM 的核心原理和应用技巧。通过详细分析内存可见性、原子性和有序性等问题,结合实际代码示例,使开发者能够更好地理解和优化多线程并发程序。 ... [详细]
  • 本文深入探讨了 MXOTDLL.dll 在 C# 环境中的应用与优化策略。针对近期公司从某生物技术供应商采购的指纹识别设备,该设备提供的 DLL 文件是用 C 语言编写的。为了更好地集成到现有的 C# 系统中,我们对原生的 C 语言 DLL 进行了封装,并利用 C# 的互操作性功能实现了高效调用。此外,文章还详细分析了在实际应用中可能遇到的性能瓶颈,并提出了一系列优化措施,以确保系统的稳定性和高效运行。 ... [详细]
  • Eclipse JFace Text框架中IDocument接口的getNumberOfLines方法详解与编程实例 ... [详细]
  • 本文作为《Java学习笔记》的开篇,旨在为初学者提供一个全面的概览。文章首先介绍了Java的基本概念及其在编程语言中的地位,强调了Java与其他主流编程语言的共通之处,特别是其核心结构,如控制语句的重要性。通过详细的目录和前言,读者可以快速了解Java的基础知识和学习路径。此外,文章还探讨了控制语句在编程中的关键作用,为后续深入学习打下坚实基础。 ... [详细]
  • 在C#中开发多线程应用程序变得高效且简便,与之前使用VB时的复杂性和局限性形成鲜明对比。C#不仅提供了丰富的多线程编程模型,还简化了线程管理、同步和通信等关键任务,使得开发者能够更加轻松地构建高性能的应用程序。此外,C#的异步编程特性进一步增强了多线程应用的开发效率和可维护性。 ... [详细]
  • BZOJ 1835: 基站位置选择问题(动态规划与线段树优化) ... [详细]
  • 在多堆石子游戏中,通过分析Nim博弈策略,探讨了如何在限定时间和内存条件下实现最优解。本文详细研究了石子游戏中的数学原理和算法优化方法,旨在为参与者提供有效的策略指导。具体而言,文章讨论了不同堆数下的Nim值计算及其应用,帮助玩家在复杂的博弈环境中取得优势。 ... [详细]
  • 本周课程涵盖了高精度计算、前缀和及差分技术。在高精度计算部分,我们将探讨如何处理任意进制的数值运算,包括但不限于正数的加法、减法和乘法。通过调整基数,可以灵活应对不同进制的需求。前缀和与差分技术则主要用于高效解决数组和区间查询问题,提升算法性能。 ... [详细]
  • 本文深入探讨了 Android DrawingView 的优化技巧与实现方法,重点介绍了如何实现平滑绘制效果。通过支持常见的绘图工具和形状,以及图层变换功能,提升了用户体验。文章详细解析了绘制过程中的性能优化策略,包括减少重绘次数、使用硬件加速和优化内存管理等技术,为开发者提供了实用的参考。 ... [详细]
  • PHP中元素的计量单位是什么? ... [详细]
author-avatar
大爱走钢索的人_738
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有