[JAVAee]阻塞队列

阻塞队列的含义

有队列这两个字的,少不了"先进先出"这个特性

阻塞队列是一种线程安全的数据结构,主要的特性有:

  • 当队列满的时候, 继续入队列就会阻塞, 直到有其他线程从队列中取走元素.
  • 当队列空的时候, 继续出队列也会阻塞, 直到有其他线程往队列中插入元素.

阻塞队列的使用 

在java标准库中,内置了阻塞队列.当我们想使用的时候,可以实现BlockingQueue接口就好(但其真正实现的类为LinkedBlockingQueue).

在队列当中,必然有方法将元素进行放置或取出.

在阻塞队列中,常用的为put方法放置元素与take方法取出元素,也只有这两种方法具有阻塞的特性.能实现阻塞队列的效果.

public static void main(String[] args) throws InterruptedException {BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();queue.put(5);//放置一个元素,如果当前队列已经满了则此线程进入阻塞状态queue.take();//取出一个元素,如果当前队列为空则此线程进入阻塞状态}

阻塞队列的模拟实现

实现阻塞队列:

  1. 实现一个循环队列()
  2. 给放置与取出方法加上阻塞功能
  3. 保证线程安全

①实现循环队列,与普通的put与take方法 

class MyBlockingQueue{private int[] array = new int[1000];//基于数组来实现队列private int size = 0;//记录队列当前的元素个数private int head = 0;//记录头节点private int tail = 0;//记录尾巴节点public void put(int value){if(size == array.length){//检测队列中的元素是否已满System.out.println("已满,勿扰");return;}array[tail++] = value;//尾插法size++;if(tail == array.length){tail = 0;//达到循环队列的效果}}public int take(){if(size == 0){System.out.println("空了空了");return -1;}int ret = array[head];head++;if(head == array.length){head = 0;//循环循环}size--;return ret;}
}

②添加阻塞功能 

分别往put与take方法加上wait与notifyAll

  • put时队列满的时候进入阻塞状态,只有等到调用take方法取走一个元素后才会唤醒线程
  • take时队列空的时候进入阻塞状态,只有等到调用put方法放置一个元素后才会唤醒线程
public void put(int value) throws InterruptedException {if(size == array.length){//检测队列中的元素是否已满wait();}array[tail++] = value;//尾插法size++;if(tail == array.length){tail = 0;//达到循环队列的效果}notifyAll();}
public int take()throws InterruptedException{if(size == 0){//检测队列是否为空wait();}int ret = array[head];head++;if(head == array.length){head = 0;//循环循环}size--;notifyAll();return ret;}

③保证线程安全 

关于线程安全要注意的是:

  • 多线程环境下的抢占式执行
  • 多个线程修改同一个变量
  • 线程的读写操作不能保证原子性

 对于此处的读写修改操作,emmm.

put方法和take方法好像一整个都是呢

所以我们可以使用synchronized关键字为他们上锁,保证原子性达到线程安全.

对于频繁修改和需要进行比较或判断的元素,也要加上volatile关键字,保证线程内存可见性.防止存在误判导致的一系列错误.

class MyBlockingQueue{private int[] array = new int[1000];//基于数组来实现队列private volatile int size = 0;//记录队列当前的元素个数private int head = 0;//记录头节点private int tail = 0;//记录尾巴节点public void put(int value) throws InterruptedException {synchronized (this) {while(size == array.length){//使用while循环,线程被唤醒后继续判断队列是否已满//真正使用的情况下不但只有两个线程//检测队列中的元素是否已满wait();}array[tail++] = value;//尾插法size++;if(tail == array.length){tail = 0;//达到循环队列的效果}notifyAll();}}public int take()throws InterruptedException{synchronized (this) {while(size == 0){//检测队列是否为空wait();}int ret = array[head];head++;if(head == array.length){head = 0;//循环循环}size--;notifyAll();return ret;}}
}

注意事项:

使用循环队列,因为线程是先进先出的情况.当尾巴节点来到了最后一个下标的时候,如果前面有进行take操作其实队列前半段是空空如也的.可以继续存放数据

在多线程的环境下,一定要注意线程安全.注意修改操作

在多线程下,判断队列是否已满或是否为空的语句最好写成while循环,在多线程下.可能线程A被唤醒后没有立即被调度,过一段时间后队列又满了,但此时如果是if语句,就无法判断队列是否满了.再进行操作会有其他数据被覆盖的风险

 

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

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

相关文章

DTH11 温湿度模块

文章目录 前言一、DTH11 模块介绍二、设备树设置三、驱动程序四、测试程序五、上机测试及效果总结 前言 DHT11 是一款可测量 温度 和 湿度 的传感器。比如市面上一些空气加湿器&#xff0c;会测量空气中湿度&#xff0c;再根据测量结果决定是否继续加湿。 一、DTH11 模块介绍 …

iOS 单元测试之常用框架 OCMock 详解

目录 前言&#xff1a; 一、单元测试 1.1 单元测试的必要性 1.2 单元测试的目的 - 约束条件是否通过形式参数来传送。 1.3 单元测试依赖的两个主要框架 二、OCMock 的集成与使用 2.1 OCMock 的集成方式 2.2 OCMock 的使用方法 2.3 mock 使用限制 前言&#xff1a; OC…

【unity】ShaderGraph学习笔记

【unity】ShaderGraph学习笔记 创建ShaderGraph 创建URP的shaderGraph文件 在Project面板里Create→ShaderGraph→URP→这里主要有几个选项 Lit Shader Graph&#xff1a;有光照三维着色器 Unlit Shader Graph&#xff1a;无光照三维着色器 Sprite Custom Lit Shader Gra…

Linux常用操作命令集合

1、 开机启动脚本的设置 如何增加一个服务&#xff1a; 服务脚本必须存放在/etc/ini.d/目录下&#xff1b;&#xff08;具体请参照Centos JDK 和tomcat部署笔记&#xff09; chkconfig --add servicename在chkconfig工具服务列表中增加此服务&#xff0c;此时服务会被在/etc/r…

Elasticsearch 简单搜索查询案例

1.MySql表结构/数据 SET FOREIGN_KEY_CHECKS0;-- ---------------------------- -- Table structure for user_lables -- ---------------------------- DROP TABLE IF EXISTS user_lables; CREATE TABLE user_lables (id varchar(255) DEFAULT NULL COMMENT 用户唯一标识,age…

CNN(卷积神经网络)的实现过程详解

概要 在图像处理领域&#xff0c;CNN(卷积神经网络)处于绝对统治地位&#xff0c;但对于CNN具体是如何用神经网络实现的&#xff0c;能找到的介绍要么是一大堆数学公式&#xff0c;要么是大段晦涩的文字说明&#xff0c;读起来很是辛苦&#xff0c;想写好一片完整的而且有深度的…

【开源项目】低代码数据可视化开发平台-Datav

Datav 基本介绍 Datav是一个Vue3搭建的低代码数据可视化开发平台&#xff0c;将图表或页面元素封装为基础组件&#xff0c;无需编写代码即可完成业务需求。 它的技术栈为&#xff1a;Vue3 TypeScript4 Vite2 ECharts5 Axios Pinia2 在线预览 账号: admin 密码: 123123预…

Spring Cloud+Spring Boot+Mybatis+uniapp+前后端分离实现知识付费平台免费搭建

Java版知识付费-轻松拥有知识付费平台 多种直播形式&#xff0c;全面满足直播场景需求 公开课、小班课、独立直播间等类型&#xff0c;满足讲师个性化直播场景需求&#xff1b;低延迟、双向视频&#xff0c;亲密互动&#xff0c;无论是互动、答疑&#xff0c;还是打赏、带货、…

Redis底层封装细节

日常我们程序员在使用redis做缓存的时候&#xff0c;很少会直接使用到RedisTemplate直接操作k-v键值对&#xff0c;而是通过对RedisTemplate原生代码的封装&#xff0c;来构建我们日常便于使用习惯的代码来操作数据&#xff0c;这里我分享一下日常基本的对RedisTemplate底层的封…

[nlp] tokenizer加速:fast_tokenizer=True

fast_tokenizer 是一个布尔值参数,用于指定是否使用快速的 tokenizer。在某些情况下,使用快速的 tokenizer 可以加快模型训练和推理速度。如果 fast_tokenizer 参数为 True,则会使用快速的 tokenizer;否则,将使用默认的 tokenizer。 快速的 tokenizer 通常使用一些技巧来减…

使用Newtonsoft直接读取Json格式文本(Linq to Json)

使用Newtonsoft直接读取Json格式文本&#xff08;Linq to Json&#xff09; 使用 Newtonsoft.Json&#xff08;通常简称为 Newtonsoft&#xff09;可以轻松地处理 JSON 格式的文本。Newtonsoft.Json 是 .NET 中一个流行的 JSON 处理库&#xff0c;它提供了丰富的功能和灵活性。…

微信小程序实现蓝牙开锁、开门、开关、指令发送成功,但蓝牙设备毫无反应、坑

文章目录 开源htmlJavaScript 开源 wx联系本人获取源码(开源): MJ682517 html <view><view class"p_l_36 p_r_36"><input class"w_100_ h_80 lh_80 ta_c b_2s_eee radius_20" value"{{instructVal}}" type"text" plac…

RocketMq 事务消息原理

Rocketmq 事务消息API使用 使用TransactionMQProducer类。 实现TransactionListener 接口覆盖其方法executeLocalTransaction和checkLocalTransaction 即可。 其中executeLocalTransaction 执行本地方法和checkLocalTransaction 事务状态回查。 玩法 简历一张本地事务表&…

51单片机定时器

51单片机定时器 1.简介 C51中的定时器和计数器是同一个硬件电路支持的&#xff0c;通过寄存器配置不同&#xff0c;就可以将他当做定时器 或者计数器使用。 确切的说&#xff0c;定时器和计数器区别是致使他们背后的计数存储器加1的信号不同。当配置为定时器使 用时&#xff0…

回归预测 | MATLAB实现TCN-BiGRU时间卷积双向门控循环单元多输入单输出回归预测

回归预测 | MATLAB实现TCN-BiGRU时间卷积双向门控循环单元多输入单输出回归预测 目录 回归预测 | MATLAB实现TCN-BiGRU时间卷积双向门控循环单元多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 ![6 基本介绍 1.MATLAB实现TCN-BiGRU时间卷积双向门控循…

JSON格式Python,Java,PHP等封装获取淘宝商品详情描述数据API

淘宝是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取淘宝天猫商品详情描述数据&#xff0c;您可以通过开放平台的接口或者直接访问淘宝天猫商城的网页来获取商品详情详细信息。以下是两种常用方法的介绍&#…

C语言假期作业 DAY 02

题目 一、选择题 1、以下程序段的输出结果是&#xff08; &#xff09; #include<stdio.h> int main() {char s[] "\\123456\123456\t";printf("%d\n", strlen(s));return 0; } A: 12 B: 13 C: 16 D: 以上都不对 2、若有以下程序&#xff0c;则运行…

实现基于UDP简易的英汉词典

文章目录 实现目标认识相关接口socketbzerobindrecvfromsendto 实现思路和注意事项完整代码Server.hppServer.ccClient.hppClient.cc 运行效果END 实现目标 实现一个服务端和一个客户端&#xff0c;客户端负责发送一个单词&#xff0c;服务端接收到后将翻译后的结果返回发送到…

Linux下C++ STL获取Mac地址

在Ubuntu下&#xff0c;你可以使用以下代码来获取MAC地址&#xff1a; #include <iostream>using namespace std;#include <iostream> #include <fstream> #include <string>std::string getMACAddress() {std::string macAddress;std::ifstream file…

蓝桥杯2023年第十四届省赛-飞机降落

题目描述 N 架飞机准备降落到某个只有一条跑道的机场。其中第 i 架飞机在 Ti 时刻到达机场上空&#xff0c;到达时它的剩余油料还可以继续盘旋 Di 个单位时间&#xff0c;即它最早 可以于 Ti 时刻开始降落&#xff0c;最晚可以于 Ti Di 时刻开始降落。降落过程需要 Li个单位时…