当前位置: 首页 > news >正文

多线程---阻塞队列+生产者消费者模型

文章目录

  • 阻塞队列
    • 自己实现一个阻塞队列(三步)
    • 标准库中的阻塞队列
    • 使用阻塞队列的优势
  • 生产者消费者模型

阻塞队列

队列(Queue)是我们熟悉的一个数据结构,它是“先进先出”的。但是并不是所有的队列都是“先进先出”的,比如:
优先级队列(PriorityQueue):基于自己的比较规则,拿出相应的值。
消息队列(MQ):在队列中引入一个“类型”,出队列的时候会指定某个类型的元素先出。

而我们今天学习的阻塞队列,它是一个“先进先出”的队列,但又有一些其他特点:

  1. 线程安全的。
  2. 带有阻塞功能:
    如果队列满,继续入队列,入队列操作就会阻塞,直到队列不满,入队列操作才能完成。
    如果队列空,继续出队列,出队列操作就会阻塞,直到队列不空,出队列操作才能完成。

自己实现一个阻塞队列(三步)

  • 实现基本队列
class MyBlockingQueue{public int[] items = new int[100];public int head = 0;public int tail = 0;public int size = 0;//入队列public void put ( int key)  {// 插入操作items[tail] = key;tail++;if (tail >= items.length) {tail = 0;}size++;}//出队列public Integer take()  {// 删除操作int ret = items[head];head++;if (head >= items.length) {head = 0;}size--;return ret;}
}
  • 保证线程安全
class MyBlockingQueue{public int[] items = new int[100];public int head = 0;public int tail = 0;public int size = 0;//入队列public void put ( int key)  {synchronized (this) {// 插入操作items[tail] = key;tail++;if (tail >= items.length) {tail = 0;}size++;}}//出队列public Integer take()  {synchronized (this) {// 删除操作int ret = items[head];head++;if (head >= items.length) {head = 0;}size--;return ret;}}
}
  • 实现阻塞功能
class MyBlockingQueue{public int[] items = new int[100];public int head = 0;public int tail = 0;public int size = 0;//入队列public void put ( int key) throws InterruptedException {synchronized (this) {//当wait被唤醒之后 size还有可能为满 所以不能一唤醒了就直接去使用 得再次判断条件是否满足// 比如:1.抛出异常  2. 三个线程同时执行 其中两个线程竞争锁 没竞争到锁的线程被唤醒之后size还为空while(size >= items.length){this.wait();}//判断队列是否为满  满了不能插入 就阻塞
//            if (size >= items.length){
//                this.wait();
//            }// 插入操作items[tail] = key;tail++;if (tail >= items.length) {tail = 0;}size++;this.notify();}}//出队列public Integer take() throws InterruptedException {synchronized (this) {//当wait被唤醒之后 size还有可能为空 所以不能一唤醒了就直接去使用 得再次判断条件是否满足while(size <= 0){this.wait();}//判断队列是否为空 空了不能删除 就阻塞
//            if (size <= 0){
//                this.wait();
//            }// 删除操作int ret = items[head];head++;if (head >= items.length) {head = 0;}size--;this.notify();return ret;}}
}

标准库中的阻塞队列

    //标准库的阻塞队列public static void main(String[] args) throws InterruptedException {BlockingQueue<Integer> blockingQueue = new LinkedBlockingDeque<>(2);//带有阻塞功能的入队列blockingQueue.put(1);blockingQueue.put(2);blockingQueue.take();blockingQueue.put(3);//带有阻塞功能的出队列System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());blockingQueue.put(4);System.out.println(blockingQueue.take());blockingQueue.put(4);}

使用阻塞队列的优势

  • 有利于代码解耦合

在这里插入图片描述
在这里插入图片描述

  • 削峰填谷

在服务器A流量激增的情况下,通过阻塞队列能够进行限流。使服务器B、C、D能够不受干扰、平稳运行。

生产者消费者模型

生产者消费者模型:描述的是多线程协同工作的一种方式。借助阻塞队列实现。

	//生产者-消费者模型public static void main(String[] args) {MyBlockingQueue myBlockingQueue = new MyBlockingQueue();Thread thread = new Thread(() -> {int n = 1;while (true){try {myBlockingQueue.put(n);} catch (InterruptedException e) {e.printStackTrace();}n++;}});Thread thread1 = new Thread(() -> {while (true){try {System.out.println(myBlockingQueue.take());} catch (InterruptedException e) {e.printStackTrace();}try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}});thread.start();thread1.start();}

相关文章:

  • 软考高项-基础知识
  • Linux学习第26天:异步通知驱动开发: 主动
  • 框架安全-CVE 复现SpringStrutsLaravelThinkPHP漏洞复现
  • vue中electron与vue通信(fs.existsSync is not a function解决方案)
  • C++ 中的仿函数 functor
  • PHP | php入门知识(if、switch、数组、数组排序、超级全局变量)
  • 6G关键新兴技术- 智能超表面(RIS)技术演进
  • DbVisualizer和DBeaver启动不来,启动报错
  • nodejs+vue食力派网上订餐系统-计算机毕业设计
  • AVL树、红黑树的介绍和实现[C++]
  • Windows 和 Linux 这2个系统在进行编程实现的时候的一些区别:
  • Flutter FittedBox
  • 【Python入门教程】基于OpenCV视频分解成图片+图片组合成视频(视频抽帧组帧)
  • HarmonyOS SDK,赋能开发者实现更具象、个性化开发诉求
  • java try throw exception finally 遇上 return break continue造成异常丢失
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • __proto__ 和 prototype的关系
  • idea + plantuml 画流程图
  • Java基本数据类型之Number
  • Laravel Telescope:优雅的应用调试工具
  • Laravel核心解读--Facades
  • spring security oauth2 password授权模式
  • VUE es6技巧写法(持续更新中~~~)
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 二维平面内的碰撞检测【一】
  • 高程读书笔记 第六章 面向对象程序设计
  • 基于axios的vue插件,让http请求更简单
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 快速体验 Sentinel 集群限流功能,只需简单几步
  • 面试总结JavaScript篇
  • 深度解析利用ES6进行Promise封装总结
  • 使用SAX解析XML
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • 仓管云——企业云erp功能有哪些?
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • ​马来语翻译中文去哪比较好?
  • # centos7下FFmpeg环境部署记录
  • (LeetCode) T14. Longest Common Prefix
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (汇总)os模块以及shutil模块对文件的操作
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (转)Sublime Text3配置Lua运行环境
  • (转)原始图像数据和PDF中的图像数据
  • (转载)(官方)UE4--图像编程----着色器开发
  • (转载)利用webkit抓取动态网页和链接
  • (轉貼) UML中文FAQ (OO) (UML)
  • (轉貼) 寄發紅帖基本原則(教育部禮儀司頒布) (雜項)
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • ***原理与防范
  • .apk 成为历史!
  • .Net FrameWork总结