生产者消费者模型(自己上锁与阻塞队列两版本)
一、什么是生产者消费者模型
生产者与消费者模式就是一个多线程并发协作的模式,在这个模式中呢,一部分线程被用于去生产数据,另一部分线程去处理数据,于是便有了形象的生产者与消费者了。而为了更好的优化生产者与消费者的关系,便设立一个缓冲区,也就相当于一个数据仓库,当生产者生产数据时锁住仓库,不让消费者访问,当消费者消费时锁住仓库,不让生产者访问仓库。举一个简单的例子,有一个生产者生产包子,他将生产好的包子放到筐中,放完包子由消费者从筐中拿出包子使用。当然筐还有一个作用就是当筐中没有包子时便锁住筐,不让消费者去筐中再拿取东西,当筐中有包子时,不让生产者再向筐中放入包子。
二.代码实现
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();}}
}
生产者消费者模型(自己上锁与阻塞队列两版本)相关推荐
- 【Linux入门】多线程(线程概念、生产者消费者模型、消息队列、线程池)万字解说
目录 1️⃣线程概念 什么是线程 线程的优点 线程的缺点 线程异常 线程异常 Linux进程VS线程 2️⃣线程控制 创建线程 获取线程的id 线程终止 等待线程 线程分离 3️⃣线程互斥 进程线程间 ...
- 【生产者消费者模型】
Linux生产者消费者模型 生产者消费者模型 生产者消费者模型的概念 生产者消费者模型的特点 生产者消费者模型优点 基于BlockingQueue的生产者消费者模型 基于阻塞队列的生产者消费者模型 模 ...
- 【Linux篇】第十六篇——生产者消费者模型
生产者消费者模型 生产者消费者模型的概念 生产者消费者模型的特点 生产者消费者模型优点 基于BlockingQueue的生产消费者模型 基于阻塞队列的生产者消费者模型 模拟实现基于阻塞队列的生产消费模 ...
- 【Linux】生产者消费者模型
文章目录 一. 什么是生产者消费者模型 1. 基本概念 2. 三种关系 3. 再次理解生产者消费者模型 二. 生产者消费者模型的优点 三. 基于BlockingQueue的生产者消费者模型 1. 准备 ...
- Linux生产者消费者模型
文章目录 生产者消费者模型 生产者消费者模型的概念 生产者消费者模型的特点 生产者消费者模型优点 基于BlockingQueue的生产者消费者模型 基于阻塞队列的生产者消费者模型 模拟实现基于阻塞队列 ...
- 爬虫--05:多线程与生产者消费者模型
Crawler - 05: Multithreading- und Produzenten-Verbrauchermodell 多线程 一.多线程的基本介绍 1.介绍 2.程序中模拟多任务 二.创建多 ...
- 多线程-生产者-消费者模型
一.前言 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例.该问题描 ...
- 三种方式实现生产者-消费者模型
前言 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例.该问题描述了 ...
- 进程锁、事件、进程队列、进程间共享数据、生产者消费者模型
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 进程锁(Lock) 锁的基本概念 锁的基本用法 模拟12306抢票软件 信号量:Semaphone 概念 Semaphore ...
- Linux基于单链表环形队列的多线程生产者消费者模型
生产者–消费者模型简述 对于生产者–消费者模型,相信我们都不陌生,因为生活中,我们无时无刻不在扮演生产者或消费者.但是对于Linux中的生产者–消费者模型,大家又了解了一个什么程度? 其实,说白了就是 ...
最新文章
- 技术图文:如何爬取一个地区的气象数据(上)?
- 港大正式启动全球招聘学术人才,计划延揽百位世界级杰出学者
- ALV GRID中实现RadioButton单选按钮
- 论理想中的技术团队——领导力
- python中输入的字怎么表示_简单讲解Python中的字符串与字符串的输入输出
- 修改RAC VIP IP
- 他在 B 站有 140 万粉丝,今天来免费带你学 Linux 了!
- Python: subprocess.Popen()不支持unicode问题解决
- 看懂友盟指数,洞察移动行业大趋势
- hibernate反向工程
- 智能配电系统监控解决方案在长白山机场配电工程的研究与应用
- 《深度学习:走向核心素养》学习体会
- STM32cubIDE 黑色主题_儿童画创意第二弹 | 绘画的秘密+万圣节主题画,10个创意教程一次看完!...
- ipv6 无状态地址管理
- wfGo 围棋 单人打谱模式
- android wifi p2p框架,7.2.1 P2P架构
- UAC1.0和UAC2.0区别
- 百度个性化地图如何在网页中使用?
- select.select
- hexo博客next主题添加对数学公式的支持
热门文章
- (凭什么断点要放入堆栈?)微机学习:第八课
- tcp协议及工作原理浅析_详解TCP/IP网络协议栈底层原理到徒手实现
- python创建列表副本的方法_Python之列表方法
- gradle java ide_用最简单的gradle代码,解决你java项目中的jar依赖之苦
- 数乌龟(母牛,兔子....)[打表法]
- python读取特定单词_Python:如何从txt文件中的特定单词开始读取到文件结尾
- 链表的基本操作:创建、插入、删除操作对应c/c++代码
- gitee java pdf转图片_openOffice word转pdf,pdf转图片优化版
- 自组织特征映射网络1
- 极客大学架构师训练营--编程的未来 面向对象 依赖倒置原则 -- 第二次作业