java学习-阻塞队列原理

JAVA 阻塞队列原理

阻塞队列,关键字是阻塞,先理解阻塞的含义,在阻塞队列中,线程阻塞有这样的两种情况:

  1. 当队列中没有数据的情况下,消费者端的所有线程都会被自动阻塞(挂起),直到有数据放
    入队列。
  2. 当队列中填满数据的情况下,生产者端的所有线程都会被自动阻塞(挂起),直到队列中有
    空的位置,线程被自动唤醒。

1. 阻塞队列的主要方法

„ 抛出异常:抛出一个异常;
„ 特殊值:返回一个特殊值(null 或 false,视情况而定)
„ 则塞:在成功操作之前,一直阻塞线程
„ 超时:放弃前只在最大的时间内阻塞
在这里插入图片描述

插入操作:

1:public abstract boolean add(E paramE):将指定元素插入此队列中(如果立即可行
且不会违反容量限制),成功时返回 true,如果当前没有可用的空间,则抛
出 IllegalStateException。如果该元素是 NULL,则会抛出 NullPointerException 异常。
2:public abstract boolean offer(E paramE):将指定元素插入此队列中(如果立即可行
且不会违反容量限制),成功时返回 true,如果当前没有可用的空间,则返回 false。
3:public abstract void put(E paramE) throws InterruptedException: 将指定元素插
入此队列中,将等待可用的空间(如果有必要)

public void put(E paramE) throws InterruptedException {
checkNotNull(paramE);
ReentrantLock localReentrantLock = this.lock;
localReentrantLock.lockInterruptibly();
try {
while (this.count == this.items.length)
this.notFull.await();//如果队列满了,则线程阻塞等待
enqueue(paramE);localReentrantLock.unlock();
} finally {
localReentrantLock.unlock();
}
}

4:offer(E o, long timeout, TimeUnit unit):可以设定等待的时间,如果在指定的时间
内,还不能往队列中加入 BlockingQueue,则返回失败。

获取数据操作:

1:poll(time):取走 BlockingQueue 里排在首位的对象,若不能立即取出,则可以等 time 参数
规定的时间,取不到时返回 null;
2:poll(long timeout, TimeUnit unit):从 BlockingQueue 取出一个队首的对象,如果在
指定时间内,队列一旦有数据可取,则立即返回队列中的数据。否则直到时间超时还没有数
据可取,返回失败。
3:take():取走 BlockingQueue 里排在首位的对象,若 BlockingQueue 为空,阻断进入等待状
态直到 BlockingQueue 有新的数据被加入。
4.drainTo():一次性从 BlockingQueue 获取所有可用的数据对象(还可以指定获取数据的个
数),通过该方法,可以提升获取数据效率;不需要多次分批加锁或释放锁。

2. Java 中的阻塞队列

  1. ArrayBlockingQueue :由数组结构组成的有界阻塞队列。
  2. LinkedBlockingQueue :由链表结构组成的有界阻塞队列。
  3. PriorityBlockingQueue :支持优先级排序的无界阻塞队列。
  4. DelayQueue:使用优先级队列实现的无界阻塞队列。
  5. SynchronousQueue:不存储元素的阻塞队列。
  6. LinkedTransferQueue:由链表结构组成的无界阻塞队列。
  7. LinkedBlockingDeque:由链表结构组成的双向阻塞队列
    在这里插入图片描述

.3. ArrayBlockingQueue(公平、非公平)

用数组实现的有界阻塞队列。此队列按照先进先出(FIFO)的原则对元素进行排序。默认情况下
不保证访问者公平的访问队列,所谓公平访问队列是指阻塞的所有生产者线程或消费者线程,当
队列可用时,可以按照阻塞的先后顺序访问队列,即先阻塞的生产者线程,可以先往队列里插入
元素,先阻塞的消费者线程,可以先从队列里获取元素。通常情况下为了保证公平性会降低吞吐
量。我们可以使用以下代码创建一个公平的阻塞队列:
ArrayBlockingQueue fairQueue = new ArrayBlockingQueue(1000,true);

4. LinkedBlockingQueue(两个独立锁提高并发)

基于链表的阻塞队列,同 ArrayListBlockingQueue 类似,此队列按照先进先出(FIFO)的原则对
元素进行排序。而 LinkedBlockingQueue 之所以能够高效的处理并发数据,还因为其对于生产者
端和消费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费
者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。
LinkedBlockingQueue 会默认一个类似无限大小的容量(Integer.MAX_VALUE)。

5. PriorityBlockingQueue(compareTo 排序实现优先)

是 一 个支持优先级的无界队列 。默认情况下元素采取自然顺序升序排列。 可以自定义实现
compareTo()方法来指定元素进行排序规则,或者初始化 PriorityBlockingQueue 时,指定构造
参数 Comparator 来对元素进行排序。需要注意的是不能保证同优先级元素的顺序。

6. DelayQueue(缓存失效、定时任务 )

是一个支持延时获取元素的无界阻塞队列。队列使用 PriorityQueue 来实现。队列中的元素必须实
现 Delayed 接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才
能从队列中提取元素。我们可以将 DelayQueue 运用在以下应用场景:

  1. 缓存系统的设计:可以用 DelayQueue 保存缓存元素的有效期,使用一个线程循环查询
    DelayQueue,一旦能从 DelayQueue 中获取元素时,表示缓存有效期到了。

  2. 定 时 任 务 调 度 : 使 用 DelayQueue 保 存 当 天 将 会 执 行 的 任 务 和 执 行 时 间 , 一 旦 从
    DelayQueue 中获取到任务就开始执行,从比如 TimerQueue 就是使用 DelayQueue 实现的。

7. SynchronousQueue(不存储数据、可用于传递数据)

是一个不存储元素的阻塞队列。每一个 put 操作必须等待一个 take 操作,否则不能继续添加元素。
SynchronousQueue 可以看成是一个传球手,负责把生产者线程处理的数据直接传递给消费者线
程。队列本身并不存储任何元素,非常适合于传递性场景,比如在一个线程中使用的数据,传递给
另 外 一 个 线 程 使 用 , SynchronousQueue 的 吞 吐 量 高 于 LinkedBlockingQueue 和
ArrayBlockingQueue。

8. LinkedTransferQueue

是 一 个 由 链 表 结 构 组 成 的 无 界 阻 塞 TransferQueue 队 列 。 相 对 于 其 他 阻 塞 队 列 ,
LinkedTransferQueue 多了 tryTransfer 和 transfer 方法。

  1. transfer 方法:如果当前有消费者正在等待接收元素(消费者使用 take()方法或带时间限制的
    poll()方法时),transfer 方法可以把生产者传入的元素立刻 transfer(传输)给消费者。如
    果没有消费者在等待接收元素,transfer 方法会将元素存放在队列的 tail 节点,并等到该元素
    被消费者消费了才返回。
  2. tryTransfer 方法。则是用来试探下生产者传入的元素是否能直接传给消费者。如果没有消费
    者等待接收元素,则返回 false。和 transfer 方法的区别是 tryTransfer 方法无论消费者是否
    接收,方法立即返回。而 transfer 方法是必须等到消费者消费了才返回。
    对于带有时间限制的 tryTransfer(E e, long timeout, TimeUnit unit)方法,则是试图把生产者传
    入的元素直接传给消费者,但是如果没有消费者消费该元素则等待指定的时间再返回,如果超时

9. LinkedBlockingDeque

是一个由链表结构组成的双向阻塞队列。所谓双向队列指的你可以从队列的两端插入和移出元素。
双端队列因为多了一个操作队列的入口,在多线程同时入队时,也就减少了一半的竞争。相比其
他 的 阻 塞 队 列 , LinkedBlockingDeque 多 了 addFirst , addLast , offerFirst , offerLast ,
peekFirst,peekLast 等方法,以 First 单词结尾的方法,表示插入,获取(peek)或移除双端队
列的第一个元素。以 Last 单词结尾的方法,表示插入,获取或移除双端队列的最后一个元素。另
外插入方法 add 等同于 addLast,移除方法 remove 等效于 removeFirst。但是 take 方法却等同
于 takeFirst,不知道是不是 Jdk 的 bug,使用时还是用带有 First 和 Last 后缀的方法更清楚。
在初始化 LinkedBlockingDeque 时可以设置容量防止其过渡膨胀。另外双向阻塞队列可以运用在
“工作窃取”模式中。

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

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

相关文章

【谷粒学院】开发篇二:后台管理系统搭建逆向生成代码

后台管理系统介绍 本篇文章主要内容如下: 1.使用人人开源人人开源绞手架搭建后台管理系统的前端和后端框架。 2.使用renren-generator逆向生成微服务(gulimall_pms、gulimall_oms、gulimall_sms、gulimall_ums、gulimall_wms)的CRUD代码。 …

探索图结构:从基础到算法应用

文章目录 理解图的基本概念学习图的遍历算法学习最短路径算法案例分析:使用 Dijkstra 算法找出最短路径结论 🎉欢迎来到数据结构学习专栏~探索图结构:从基础到算法应用 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒🍹✨博客主页:I…

Jmeter常用线程组设置策略

一、前言 ​ 在JMeter压力测试中,我们时常见到的几个场景有:单场景基准测试、单场景并发测试、单场景容量测试、混合场景容量测试、混合场景并发测试以及混合场景稳定性测试 在本篇文章中,我们会用到一些插件,在这边先给大家列出&…

一款轻量级开发者工具,提高开发效率

Devkits Devkits 是一款轻量级桌面端应用,提供了一系列开发者工具,提高开发效率。 离线。类似的在线工具已经不少了,但是大多数都是在线的,网络不好的时候就很难用了。Devkits 提供了离线使用的功能,可以在没有网络的…

Vue2向Vue3过度Vue3组合式API

目录 1. Vue2 选项式 API vs Vue3 组合式API2. Vue3的优势3 使用create-vue搭建Vue3项目1. 认识create-vue2. 使用create-vue创建项目 4 熟悉项目和关键文件5 组合式API - setup选项1. setup选项的写法和执行时机2. setup中写代码的特点3. <script setup>语法糖 6 组合式…

反射机制-体会反射的动态性案例(尚硅谷Java学习笔记)

// 举例01 public class Reflect{ // 静态性 public Person getInstance(){return new Person(); }// 动态性 public T<T> getInstance(String className) throws Exception{Calss clzz Class.forName(className);Constructor con class.getDeclaredConstructor();con…

linux————haproxy

一、概述 HAProxy是一个免费的负载均衡软件&#xff0c;可以运行于大部分主流的Linux操作系统上&#xff08;CentOS、Ubuntu、Debian、OpenSUSE、Fedora、麒麟、欧拉、UOS&#xff09;。 HAProxy提供了L4(TCP)和L7(HTTP)两种负载均衡能力&#xff0c;具备丰富的功能。HAProxy具…

无涯教程-PHP.INI File Configuration函数

PHP配置文件php.ini是影响PHP功能的最终且最直接的方法。每次初始化PHP时都会读取php.ini文件。换句话说,无论是模块版本的httpd重新启动还是CGI版本的每次脚本执行都重新启动。如果未显示您的更改,请记住停止并重新启动httpd。 该配置文件已注释完整。键区分大小写,关键字值不…

python实现的淘宝自动发货脚本

pyhton # 文件用ini # 自动应答&#xff0c;自动点发货

leetcode496. 下一个更大元素 I 【单调栈】

【简单题】&#xff08;暴力遍历法很简单&#xff09;但是时间复杂度很高&#xff0c;n的立方级别了。。。 代码&#xff1a; class Solution { public:vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {vector<int&g…

gitee远程仓库——Git常用远程仓库托管服务

远程仓库 我们的代码不能总是放在本地&#xff0c;因为总是放在本地&#xff0c;一旦电脑出现故障&#xff0c;数据将丢失&#xff0c;怎么共享呢&#xff1f;这里我们需要一个服务器&#xff0c;我们可以把代码放到服务器上&#xff0c;然后让别人下载&#xff0c;这样我们既…

k8s-dashboard使用指导手册

一、访问 dashboard http://172.66.209.101:32001 二、选择 Namespace 如下图&#xff1a; 1 在①搜索框中输入 spms 2 在②选择 spms-cloud 三、查找 pod 1 打开 pod 列表 2 打开过滤窗口 3 搜索 pod 在打开的搜索框中输入 pod的关键字&#xff0c;支持模糊搜索 如搜索…

“石头剪刀布”游戏:while、函数自调用实现循环游戏

if…else实现“石头剪刀布”游戏&#xff0c;while、函数自调用实现循环游戏。 (本笔记适合学过if…else的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c…

ArcGIS学习总结(19)——要素转点与空间连接(属性表字段映射)

1.在新创建的面矢量数据的属性表中没有对应的字段信息&#xff0c;为了能够和有属性信息的数据进行匹配&#xff0c;使其具有对应字段的信息。 2.需要匹配的矢量文件属性表信息。 3.对新创建的矢量文件执行要素转点&#xff1a;数据管理工具→要素→要素转点。 4.选择分析工…

Docker安装MySQL、Redis如何自启?

1、问题&#xff1a; Docker自启&#xff1a;http://t.csdn.cn/L2v55 重新启动虚拟机&#xff0c;Docker自动启动之后&#xff0c;发现MySQL、Redis都没有启动。 docker ps 没查到有启动的容器。 docker ps -a 查看所有的容器。 2、先使用 su root 命令&#xff0c;切换到root…

小程序如何手动变更会员卡等级

有时候需要商家手动变更会员卡等级&#xff0c;以让会员获取更多的福利和特权。下面就介绍一些小程序手动变更会员卡等级的常见方法和策略。 1. 找到指定的会员卡。在管理员后台->会员管理处&#xff0c;找到需要更改等级的会员卡。也支持对会员卡按卡号、手机号和等级进行…

盖雅工场获评2023年度苏州市服务型制造示范企业(平台)

苏州市工信局公布 2023年度苏州市服务型制造示范企业&#xff08;平台&#xff09;名单 遴选出服务型制造示范企业34家 服务型制造示范平台19个 苏州盖雅信息技术有限公司 “劳动力管理SaaS云平台服务” 获评2023年度苏州市服务型制造示范平台 全市唯一获评的人力资源服务…

7.接着跑一下triton官方教程

5.Model Ensemble 在此示例中&#xff0c;我们将探索使用模型集成来仅通过单个网络调用在服务器端执行多个模型。这样做的好处是减少了在客户端和服务器之间复制数据的次数&#xff0c;并消除了网络调用固有的一些延迟。 为了说明创建模型集成的过程&#xff0c;我们将重用第…

C#__使用Thread启动线程和传输数据

class Program{static void Test(){Console.WriteLine("Start……");Thread.Sleep(2000); // 1s等于1000ms&#xff0c;暂停2sConsole.WriteLine("end");}static void Download(Object ob){string str ob as string; // 遍历传递过来的ob字符串Console.Wr…

[MySQL]主从服务器布置

配置主服务器 配置文件 /etc/my.cnf 在[mysqld]下进行配置 log_binON //启动二进制日志 log-bin mysql-bin //启用二进制日志&#xff0c;用于记录主服务器的更新操作 server-id 1 // 用来表示mysql服务id,保证集成环境中的唯一性 , 范围 [1,2^32) read-only0 // 1表示只…