阻塞队列和基本实现

1. 什么是阻塞队列

阻塞队列,从名字上看,它首先应该是一个队列,满足先进先出的原则.其次,我们来理解一下"阻塞"这个词.我们之前其实见过这个词,在介绍线程的状态时,我们讲过有一种状态就是阻塞状态.所谓的"阻塞",也就是一种等待,需要其他的线程进行唤醒,在这里也确实是这层意思.阻塞队列中存放的是Runnable对象,代表着需要进行的操作.

总结一下,阻塞队列就是一个可以内置阻塞状态的队列.

2. 阻塞队列的结构

我们刚刚提过:阻塞队列是一个队列,但它是一个普通的队列吗?并不是,阻塞队列实际上底层使用的是循环队列.为什么呢?因为阻塞队列需要"阻塞",什么时候阻塞呢?就是队列为满的时候,使用一个普通的队列,就不存在一个满的概念,除非人为设置一个阈值.在这种情况下,不如使用循环队列进行实现更为直观.

3. put和take方法

在阻塞队列中,内置了两个非常重要的方法put方法和take方法.

put方法

在put方法中,我们需要做的就是把Runnable对象添加进入阻塞队列.当队列不为满时,我们就可以将这个过程简要理解为对一个不满的循环队列添加元素.

但是,当队列满时,我们就没有办法再把Runnable对象添加进阻塞队列,那么调用put方法的这个线程就要进入阻塞等待状态.

take方法

在take方法中,我们需要做的就是把Runnable对象从阻塞队列中取出,当队列不为空时,我们就可以将这个过程简要理解为对一个不为空的循环队列删除元素.

同样,当队列空时,我们没法取出其中的Runnable对象,调用take方法的这个线程也要进入阻塞等待状态.

两个方法的联系

我们刚才还没有解决一个问题,调用put方法的线程和调用take方法的线程进入阻塞等待后,谁去唤醒它们,答案就是-------除了自己的另一个线程.

我们思考一下,对同一个循环队列进行put和take,上述两个线程中至多只有一个线程进入阻塞等待状态,因为同一个循环队列不能又空又满,这就意味着两个线程必定可以互相唤醒,相辅相成.

代码实现:

当然在这个过程中,要解决线程安全问题:

public class MyBlockingQueue {private String[] elems;int head = 0;int tail = 0;int size = 0;//通过计数实现循环队列public MyBlockingQueue(int capacity) {elems = new String[capacity];}public void put(String elem) throws InterruptedException {synchronized (this) {if (size >= elems.length) {//队列满了this.wait();}elems[tail] = elem;tail++;if (tail >= elems.length) {tail = 0;}size++;this.notify();}}public String take() throws InterruptedException {synchronized (this) {if (size == 0) {this.wait();}String res = elems[head];head++;if (head >= elems.length) {head = 0;}size--;this.notify();return res;}}

4. 阻塞队列的经典应用-----生产者消费者模型

所谓生产者消费者模型,就是利用循环队列,开启两个线程t1,t2.t1线程负责调用put方法,t2线程负责调用take方法,相当于线程t1进行生产,线程t2进行消耗,相辅相成.

下面直接给出代码:

public static void main(String[] args) {MyBlockingQueue q = new MyBlockingQueue(10);Thread t1 = new Thread(()->{try {int count = 1;while(true) {q.put(count+" ");System.out.println("t1生产了"+count);count++;}}catch(InterruptedException e) {e.printStackTrace();}});Thread t2 = new Thread(()->{try {while (true) {String s = q.take();System.out.println("t2消费了"+s);}}catch(InterruptedException e) {e.printStackTrace();}});t1.start();t2.start();}
}

得到的效果如下图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/808432.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

跟TED演讲学英文:The next grand challenge for AI by Jim Fan

The next grand challenge for AI Link: https://www.ted.com/talks/jim_fan_the_next_grand_challenge_for_ai? Speaker: Jim Fan Date: October 2023 文章目录 The next grand challenge for AIIntroductionVocabularyTranscriptSummary后记 Introduction Researcher Jim…

Terraform 语法配置

配置语法 Terraform 的配置文件都是以 .tf 为后缀Terraform 支持两种模式 HCL、JSON Provider 插件 providers 地址:Terraform Registry Terraform 通过 provider 管理基础设施,使用 provider 与云供应商 API 进行交互,每个 Provider 都包含…

多线程的学习

多线程编辑: 可以简单理解进程是一个软件 而线程就是一个软件中多个可以同时运行的功能 实现多线程的第一种方式:使用Thead类我们再自己创造一个类继承于这个类我们在对Thead方法进行重写,注意我们再重写的时候一定要加上Override这行 我犯下…

多线程回答的滚瓜烂熟,面试官问我虚线程了解吗?我说不太了解!

Java虚拟线程(Virtual Threads)标志着Java在并发编程领域的一次重大飞跃,特别是从Java 21版本开始。这项新技术的引入旨在克服传统多线程和线程池存在的挑战。 多线程和线程池 在Java中,传统的多线程编程依赖于Thread类或实现Ru…

2024 年“认证杯”数学中国数学建模网络挑战赛

题目 C题 云中的海盐 巴黎气候协定提出的目标是:在 2100 年前,把全球平均气温相对于工业 革命以前的气温升幅控制在不超过 2 摄氏度的水平,并为 1.5 摄氏度而努力。 但事实上,许多之前的研究已经指出,全球的碳排放以及…

主从数据同步原理

2.2.主从数据同步原理 2.2.1.全量同步 主从第一次建立连接时,会执行全量同步,将master节点的所有数据都拷贝给slave节点,流程: 这里有一个问题,master如何得知salve是第一次来连接呢?? 有几个…

Linux操作系统的学习

Linux系统的目录结构 / 是所有目录的顶点目录结构像一颗倒挂的树 Linux常用命令 常见命令 序号命令对应英文作用1lslist查看当前目录下的内容2pwdprint work directory查看当前所在目录3cd [目录名]change directory切换目录4touch [文件名]touch如果文件不存在,新…

6.11物联网RK3399项目开发实录-驱动开发之定时器的使用(wulianjishu666)

嵌入式实战开发例程【珍贵收藏,开发必备】: 链接:https://pan.baidu.com/s/1tkDBNH9R3iAaHOG1Zj9q1Q?pwdt41u 定时器使用 前言 RK3399有 12 个 Timers (timer0-timer11),有 12 个 Secure Timers(stimer0~stimer11) 和 2 个 …

鸿蒙实战开发-如何实现标准化数据定义与描述的功能。

介绍 本示例主要使用ohos.data.uniformTypeDescriptor 展示了标准化数据定义与描述的功能,在新增预置媒体文件后,对媒体文件的utd标准类型获取、utd类型归属类型查询、获取文件对应的utd类型的默认图标、支持自定义数据类型等功能。 实现过程中还使用到…

AcWing-直方图中最大的矩形

131. 直方图中最大的矩形 - AcWing题库 所需知识:单调栈 思路:要求最大矩形,所以需要使矩形的高与长的乘积最大即可,依次从左到右将每一列当作中心列,向两边扩散,直到两边的高都小于该列的高,…

Vmware虚拟机Centos7固定IP地址

1、点击编辑-虚拟网络编辑器 2、点击更改设置、修改虚拟网络配置器并确认保存(见图) 这个子网IP和子网掩码的前三位需要一样网关的前三位需要和子网ip一致。 3、打开设置“网络和Internet”,点击“更改适配器选项”,点击适配器VM…

PP-LCNet:一种轻量级CPU卷积神经网络

PP-LCNet: A Lightweight CPU Convolutional Neural Network 最近看了一个新的分享,在图像分类的任务上表现良好,具有很高的实践意义。 论文: https://arxiv.org/pdf/2109.15099.pdf项目: https://github.com/PaddlePaddle/Padd…

JUC并发编程2(高并发,AQS)

JUC AQS核心 当有线程想获取锁时,其中一个线程使用CAS的将state变为1,将加锁线程设为自己。当其他线程来竞争锁时会,判断state是不是0,不是自己就把自己放入阻塞队列种(这个阻塞队列是用双向链表实现)&am…

探索ChatGPT-Plus:AI 助手全套开源解决方案

探索ChatGPT-Plus:AI 助手全套开源解决方案 ChatGPT-plus是一种新型的对话生成模型,它是在OpenAI的ChatGPT基础上进行了改进和优化的版本。ChatGPT-plus的出现引起了广泛关注,因为它在对话生成方面展现出了更加出色的表现和能力。在本文中&am…

蒙特卡洛方法【强化学习】

强化学习笔记 主要基于b站西湖大学赵世钰老师的【强化学习的数学原理】课程,个人觉得赵老师的课件深入浅出,很适合入门. 第一章 强化学习基本概念 第二章 贝尔曼方程 第三章 贝尔曼最优方程 第四章 值迭代和策略迭代 第五章 强化学习实践—GridWorld 第…

make/makefile学习

文章目录 1、makefile函数1.1、字符串替换函数:subst1.2、模式字符串替换函数:patsubst1.3、去空格函数:strip1.4、查找字符串函数:findstring 2、、:、?区别 1、makefile函数 1.1、字符串替换函数:subst …

《QT实用小工具·二十》存款/贷款计算器

1、概述 源码放在文章末尾 该项目实现了用于存款和贷款的计算器的功能&#xff0c;如下图所示&#xff1a; 项目部分代码如下&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget>namespace Ui { class Widget; }class Widget : public QWidget {Q_OBJ…

构造函数,原型对象,对象实例 以及原型链的关系

当我们使用构造函数new的方式创建实例对象&#xff0c;此时构造函数的.prototype属性就是实例对象的原型对象&#xff0c;实例对象可以通过.__proto__来访问到原型对象&#xff0c;同时实例对象会继承原型对象的属性方法。 构造函数和原型对象的关系其实是被包含的关系&#x…

【电子通识】普通电阻、敏感电阻、可调电阻的种类和特点

电阻的作用 在【分立元件】理解电阻 中我们知道电阻是在电路中对电流产生阻碍作用的元件。电阻是电子产品中最基本、最常用的电子元件之一。 有各产品的电路板中基本都有电阻器&#xff0c;通常起限流、滤波或分压等作用。实际上&#xff0c;电阻器的种类很多&#xff0c;根据其…

中服云数字孪生平台 3.0 版全新升级!不仅更好看,而且更好用!

近日&#xff0c;中服云数字孪生平台迎来版本升级。中服云数字孪生平台 3.0 版&#xff0c;以物联网平台 数据中台为基础&#xff0c;以 2D/3D 为展示形式&#xff0c;旨在打造一个从设备数据到孪生应用的一站式数智化平台。 中服云数字孪生平台架构 新版升级 功能急速迭代 …