一、什么是生产者消费者模型

生产者与消费者模式就是一个多线程并发协作的模式,在这个模式中呢,一部分线程被用于去生产数据,另一部分线程去处理数据,于是便有了形象的生产者与消费者了。而为了更好的优化生产者与消费者的关系,便设立一个缓冲区,也就相当于一个数据仓库,当生产者生产数据时锁住仓库,不让消费者访问,当消费者消费时锁住仓库,不让生产者访问仓库。举一个简单的例子,有一个生产者生产包子,他将生产好的包子放到筐中,放完包子由消费者从筐中拿出包子使用。当然筐还有一个作用就是当筐中没有包子时便锁住筐,不让消费者去筐中再拿取东西,当筐中有包子时,不让生产者再向筐中放入包子。

二.代码实现

1.基于await()/signal()与可重入锁的代码

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;/*** Created by WanYue*/public class ProducerCustomerModel {//维护一个临界区域private Queue<Integer> queue = new LinkedList<Integer>();//区域的最大值final static int MAX = 10;ReentrantLock lock = new ReentrantLock();//表示队列满了Condition full = lock.newCondition();//表示队列是空的Condition empty = lock.newCondition();int readData() throws InterruptedException {Thread.sleep((long)Math.random()*1000);return (int) Math.floor(Math.random());}//Producerpublic void readDb() throws InterruptedException{//必须锁住不是一下子就超过10了 就死锁了。lock.lock();
//        synchronized (queue){//满了就不生产了if(queue.size() == MAX){//monitor休眠方法//  queue.wait();//condition的指定休眠full.await();return;}//如果存在一个就唤醒消费者来消费if(queue.size() == 1) empty.signalAll();//没有满 就去生产int data = readData();queue.add(data);lock.unlock();
//        }}//Consumer,它的作用是计算public void calculate() throws InterruptedException{lock.lock();
//        synchronized (queue){//如果队列没有东西,就无法消费if(queue.size() == 0){
//                queue.wait();//condition的指定休眠empty.await();return;}//只要有一个空位就让生产者来生产if(queue.size() == MAX - 1) full.signalAll();Integer data = queue.remove();System.out.println("queue-size:" + queue.size());data *= 100;
//        }lock.unlock();}/*** 直接用唤醒notify会被卡死* P0 P1* C0* P0 C0 (都处于sleeping) C0 -> notify(p0 丨 p1)*P1 执行后queue.size() == 1 ,唤醒了P0 ,P1,把生产的放入queue,size=2了, P0就开始生产,不会执行了notify,因为不可能等于1了,因此* 需要notifyAll()都要将其唤醒 强行一起唤醒,* 需要改进的, 用一个两个Condition解决full,empty*/public static void main(String[] args) {ProducerCustomerModel p = new ProducerCustomerModel();//开100个线程开始生产,生产一般都比消费慢for (int i = 0; i < 100; i++) {new Thread(() -> {while(true){try {p.readDb();} catch (InterruptedException e) {e.printStackTrace();}}}).start();}//一个消费者就可以了new Thread(() -> {//消费者一直来回去看是否有可以消费的没。  没有while只会执行一次while(true){try {p.calculate();} catch (InterruptedException e) {e.printStackTrace();}}}).start();}}

2.基于阻塞队列的take()与put()的实现

实际上阻塞队列的底层还是ReentLock

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;/*** Created by WanYue*/public class BlockingQueueTest {public static void main(String[] args) {//记录取的次数AtomicInteger count = new AtomicInteger();BlockingQueue<Integer> queue;//queue = new LinkedBlockingQueue<>(10); //前10个有效,后面全是Nullqueue = new ArrayBlockingQueue<>(10);
//         queue = new LinkedBlockingDeque<>();
//        queue = new PriorityBlockingQueue<>();
//       queue = new SynchronousQueue<>();
//        queue = new DelayQueue<Integer>();//Producer,开30个线程去生产,说明只是生产30个for (int i = 0; i < 30; i++) {new Thread(() -> {try {//如果想一直生产那就这里用一个死循环即可queue.put((int) (Math.random() * 1_000));} catch (InterruptedException e) {e.printStackTrace();}}).start();}//Consumer,10个线程消费for (int i = 0; i < 10; i++) {new Thread(() -> {//一直轮询去访问while(true){//开始消费Integer x = null;try {x = (Integer) queue.take();count.getAndIncrement();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Receive: " + x  +" count:" + count);try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}).start();}}
}

生产者消费者模型(自己上锁与阻塞队列两版本)相关推荐

  1. 【Linux入门】多线程(线程概念、生产者消费者模型、消息队列、线程池)万字解说

    目录 1️⃣线程概念 什么是线程 线程的优点 线程的缺点 线程异常 线程异常 Linux进程VS线程 2️⃣线程控制 创建线程 获取线程的id 线程终止 等待线程 线程分离 3️⃣线程互斥 进程线程间 ...

  2. 【生产者消费者模型】

    Linux生产者消费者模型 生产者消费者模型 生产者消费者模型的概念 生产者消费者模型的特点 生产者消费者模型优点 基于BlockingQueue的生产者消费者模型 基于阻塞队列的生产者消费者模型 模 ...

  3. 【Linux篇】第十六篇——生产者消费者模型

    生产者消费者模型 生产者消费者模型的概念 生产者消费者模型的特点 生产者消费者模型优点 基于BlockingQueue的生产消费者模型 基于阻塞队列的生产者消费者模型 模拟实现基于阻塞队列的生产消费模 ...

  4. 【Linux】生产者消费者模型

    文章目录 一. 什么是生产者消费者模型 1. 基本概念 2. 三种关系 3. 再次理解生产者消费者模型 二. 生产者消费者模型的优点 三. 基于BlockingQueue的生产者消费者模型 1. 准备 ...

  5. Linux生产者消费者模型

    文章目录 生产者消费者模型 生产者消费者模型的概念 生产者消费者模型的特点 生产者消费者模型优点 基于BlockingQueue的生产者消费者模型 基于阻塞队列的生产者消费者模型 模拟实现基于阻塞队列 ...

  6. 爬虫--05:多线程与生产者消费者模型

    Crawler - 05: Multithreading- und Produzenten-Verbrauchermodell 多线程 一.多线程的基本介绍 1.介绍 2.程序中模拟多任务 二.创建多 ...

  7. 多线程-生产者-消费者模型

    一.前言 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例.该问题描 ...

  8. 三种方式实现生产者-消费者模型

    前言 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例.该问题描述了 ...

  9. 进程锁、事件、进程队列、进程间共享数据、生产者消费者模型

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 进程锁(Lock) 锁的基本概念 锁的基本用法 模拟12306抢票软件 信号量:Semaphone 概念 Semaphore ...

  10. Linux基于单链表环形队列的多线程生产者消费者模型

    生产者–消费者模型简述 对于生产者–消费者模型,相信我们都不陌生,因为生活中,我们无时无刻不在扮演生产者或消费者.但是对于Linux中的生产者–消费者模型,大家又了解了一个什么程度? 其实,说白了就是 ...

最新文章

  1. 技术图文:如何爬取一个地区的气象数据(上)?
  2. 港大正式启动全球招聘学术人才,计划延揽百位世界级杰出学者
  3. ALV GRID中实现RadioButton单选按钮
  4. 论理想中的技术团队——领导力
  5. python中输入的字怎么表示_简单讲解Python中的字符串与字符串的输入输出
  6. 修改RAC VIP IP
  7. 他在 B 站有 140 万粉丝,今天来免费带你学 Linux 了!
  8. Python: subprocess.Popen()不支持unicode问题解决
  9. 看懂友盟指数,洞察移动行业大趋势
  10. hibernate反向工程
  11. 智能配电系统监控解决方案在长白山机场配电工程的研究与应用
  12. 《深度学习:走向核心素养》学习体会
  13. STM32cubIDE 黑色主题_儿童画创意第二弹 | 绘画的秘密+万圣节主题画,10个创意教程一次看完!...
  14. ipv6 无状态地址管理
  15. wfGo 围棋 单人打谱模式
  16. android wifi p2p框架,7.2.1 P2P架构
  17. UAC1.0和UAC2.0区别
  18. 百度个性化地图如何在网页中使用?
  19. select.select
  20. hexo博客next主题添加对数学公式的支持

热门文章

  1. (凭什么断点要放入堆栈?)微机学习:第八课
  2. tcp协议及工作原理浅析_详解TCP/IP网络协议栈底层原理到徒手实现
  3. python创建列表副本的方法_Python之列表方法
  4. gradle java ide_用最简单的gradle代码,解决你java项目中的jar依赖之苦
  5. 数乌龟(母牛,兔子....)[打表法]
  6. python读取特定单词_Python:如何从txt文件中的特定单词开始读取到文件结尾
  7. 链表的基本操作:创建、插入、删除操作对应c/c++代码
  8. gitee java pdf转图片_openOffice word转pdf,pdf转图片优化版
  9. 自组织特征映射网络1
  10. 极客大学架构师训练营--编程的未来 面向对象 依赖倒置原则 -- 第二次作业