ArrayBlockingQueue

2023-10-26

在java多线程操作中, BlockingQueue<E> 常用的一种方法之一。在看jdk内部尤其是一些多线程,大量使用了blockinkQueue 来做的。 

借用jdk api解释下:

BlockingQueue 方法以四种形式出现,对于不能立即满足但可能在将来某一时刻可以满足的操作,这四种形式的处理方式不同:第一种是抛出一个异常,第二种是返回一个特殊值(null 或 false,具体取决于操作),第三种是在操作可以成功前,无限期地阻塞当前线程,第四种是在放弃前只在给定的最大时间限制内阻塞。下表中总结了这些方法:

  抛出异常 特殊值 阻塞 超时
插入 add(e) offer(e) put(e) offer(e, time, unit)
移除 remove() poll() take() poll(time, unit)
检查 element() peek() 不可用 不可用

ArrayBlockingQueue介绍

ArrayBlockingQueue是一个阻塞式的队列,继承自AbstractBlockingQueue,间接的实现了Queue接口和Collection接口。底层以数组的形式保存数据(实际上可看作一个循环数组)。常用的操作包括 add,offer,put,remove,poll,take,peek。

根据 ArrayBlockingQueue 的名字我们都可以看出,它是一个队列,并且是一个基于数组的阻塞队列。

ArrayBlockingQueue 是一个有界队列,有界也就意味着,它不能够存储无限多数量的对象。所以在创建 ArrayBlockingQueue 时,必须要给它指定一个队列的大小。

我们先来熟悉一下 ArrayBlockingQueue 中的几个重要的方法。

  • add(E e):把 e 加到 BlockingQueue 里,即如果 BlockingQueue 可以容纳,则返回 true,否则报异常 
  • offer(E e):表示如果可能的话,将 e 加到 BlockingQueue 里,即如果 BlockingQueue 可以容纳,则返回 true,否则返回 false 
  • put(E e):把 e 加到 BlockingQueue 里,如果 BlockQueue 没有空间,则调用此方法的线程被阻断直到 BlockingQueue 里面有空间再继续
  • poll(time):取走 BlockingQueue 里排在首位的对象,若不能立即取出,则可以等 time 参数规定的时间,取不到时返回 null 
  • take():取走 BlockingQueue 里排在首位的对象,若 BlockingQueue 为空,阻断进入等待状态直到 Blocking 有新的对象被加入为止 
  • remainingCapacity():剩余可用的大小。等于初始容量减去当前的 size

ArrayBlockingQueue 使用场景。

  • 先进先出队列(队列头的是最先进队的元素;队列尾的是最后进队的元素)
  • 有界队列(即初始化时指定的容量,就是队列最大的容量,不会出现扩容,容量满,则阻塞进队操作;容量空,则阻塞出队操作)
  • 队列不支持空元素

 

保存数据的结构

/** The queued items */
final Object[] items;

可以看到,是一个Object的数组。

全局锁

/** Main lock guarding all access */
final ReentrantLock lock;

注视也说明了,这是一个掌管所有访问操作的锁。全局共享。都会使用这个锁。

ArrayBlockingQueue 进队操作采用了加锁的方式保证并发安全。源代码里面有一个 while() 判断:

public void put(E e) throws InterruptedException {
    checkNotNull(e); // 非空判断
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly(); // 获取锁
    try {
        while (count == items.length) {
            // 一直阻塞,知道队列非满时,被唤醒
            notFull.await();
        }
        enqueue(e); // 进队
    } finally {
        lock.unlock();
    }
}
public boolean offer(E e, long timeout, TimeUnit unit)
    throws InterruptedException {
    checkNotNull(e);
    long nanos = unit.toNanos(timeout);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == items.length) {
        // 阻塞,知道队列不满
        // 或者超时时间已过,返回false
            if (nanos <= 0)
                return false;
            nanos = notFull.awaitNanos(nanos);
        }
        enqueue(e);
        return true;
    } finally {
        lock.unlock();
    }
}

通过源码分析,我们可以发现下面的规律:

  • 阻塞调用方式 put(e)或 offer(e, timeout, unit)
  • 阻塞调用时,唤醒条件为超时或者队列非满(因此,要求在出队时,要发起一个唤醒操作)
  • 进队成功之后,执行notEmpty.signal()唤起被阻塞的出队线程

出队的源码类似。ArrayBlockingQueue 队列我们可以在创建线程池时进行使用。

new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(2));

PS:在进行某项业务存储操作时,建议采用offer进行添加,可及时获取boolean进行判断,如用put要考虑阻塞情况(队列的出队操作慢于进队操作),资源占用。

有兴趣的可以顺便了解下 LinkedBlockingQueue 

文章参考:

BlockingQueue中 take、offer、put、add的一些比较 

ArrayBlockingQueue详解

ArrayBlockingQueue 使用

深入剖析java并发之阻塞队列LinkedBlockingQueue与ArrayBlockingQueue

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ArrayBlockingQueue 的相关文章

  • 如何在编写 XML 文件时忽略 DTD 验证但保留 Doctype?

    我正在开发一个系统 该系统应该能够读取任何 或至少是任何格式良好的 XML 文件 操作一些节点并将它们写回到同一个文件中 我希望我的代码尽可能通用 但我不希望 对代码中任何位置的架构 文档类型信息的硬编码引用 文档类型信息位于源文档中 我想
  • 按钮和窗口之间的空间

    我这里有这段代码 其想法是在主窗口中在文本区域旁边有两个按钮 但我尚未添加 在尝试使用 GridBagLayout 并在此过程中扯掉我的头发后 我决定不使用布局并在不可调整大小的窗口内手动放置按钮 import java awt impor
  • 查找“”之间的字符串的正则表达式是什么

    我有一个字符串如下 http 172 1 10 1 3 http 192 168 15 2 6 http 192 168 1 100 1 2 8 内的字符串是一个标签 内的字符串是前面标签的值 返回我的正则表达式是什么 标签 http 17
  • 删除最低位

    给定一个二进制数 删除最低位的最快方法是什么 01001001010 gt 01001001000 它将在代码中用于迭代变量的位 伪代码如下 while bits 0 index getIndexOfLowestOrderBit bits
  • 从列表中删除对象的最佳方法是什么

    我有以下逻辑来删除系统中的非活动用户 因为我们在迭代列表时无法删除行 有更好的方法来处理这个问题吗 List
  • 将 uiautomator 测试用例与 Android 中的应用程序代码集成

    我正在使用 Eclipse IDE 这是我的 uiautomator 测试用例代码 public class caltest extends UiAutomatorTestCase public void testDemo throws U
  • 如何在活动之间传递大型集合(主从流)

    背景 我正在实现一个从网络服务读取有关电影信息的应用程序 该网络服务返回有关每部电影的一些信息 标题 日期 海报网址 导演 演员等 该 Web 服务支持分页 因此电影以 100 部为一组加载 执行 这个想法是显示一个包含所有海报的网格 当用
  • 根据条件更改 JSlider 的最小值和最大值

    我正在 Netbeans 中创建 Swing GUI 此 GUI 的目的是打开一个 缓冲 图像 在 JLabel 中作为图标 并对其应用仿射变换 现在我正在做 4 个转换 如下所示 现在 每个变换都需要两个滑块来更改 X 和 Y 值 但旋转
  • Spring方法获取给定类型的所有bean

    我试图从一个相同类型的豆子中获取所有豆子FileSystemXmlApplicationContext 我正在使用factory getBeansOfType SomeType class 但我注意到它只返回顶级 bean 是否有任何其他方
  • 更新写入 java 文本文件的对象

    将 Java 对象或列表写入文本文件是可以的 但我想知道如何更新或重写以前写入的对象而不再次写入对象 例如 假设有一个 java util List 有一组对象 然后将该列表写入文本文件 然后稍后该文件将被再次读取并从列表中获取所有对象 然
  • 如何在 spring-boot 中禁用 spring-data-mongodb 自动配置

    有没有人尝试过在 spring boot 中禁用 mongodb 的自动配置 我正在尝试使用 spring data mongodb 来启动 spring boot 使用基于java的配置 使用 spring boot 1 2 1 RELE
  • 如何在应用程序级别管理只读数据库连接

    我们使用的是Java Spring Ibatis MySql 有没有办法利用这些技术在应用程序级别管理只读连接 我希望在只读 MySql 用户的基础上添加额外的保护层 如果 BasicDataSource 或 SqlMapClientTem
  • JAXB 是否支持 xsd:restriction?

  • @Where 子句在 hibernate join 查询中不起作用

    我有 2 个带有 Where 注释的实体 第一个是类别 Where clause DELETED 0 public class Category extends AbstractEntity 且有如下关系 OneToMany fetch F
  • 使用 lambda 或 Stream API 合并流以生成交替序列

    我有一些按预期返回 Stream 的代码 但也许可以用某种类型的 lambda 或 stream 操作替换它 而不是耗尽 a 中的迭代器while loop 它只是一种交替流中元素的方法first and second当其中一个元素耗尽时停
  • 在文件中查找一行并将其删除

    我正在寻找一个小代码片段 它将在文件中找到一行并删除该行 不是内容而是行 但找不到 例如 我在以下文件中 我的文件 txt aaa bbb ccc ddd 需要有这样的功能 public void removeLine String lin
  • 使用 HttpClient 在 java 中进行连接池 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 如何使用 HttpClient 创建连接池 我必须频繁连接到同一台服务器 值得创建这样一个池吗 是否可以保持 HTTP 连接处于活动状
  • 无法在 JDBCPreparedStatement 中使用 LIKE 查询吗?

    查询代码及查询方式 ps conn prepareStatement select instance id from eam measurement where resource id in select RESOURCE ID from
  • 为什么浮点数有符号零?

    为什么双打有 0也 0 其背景和意义是什么 0 通常 被视为0 当一个negative浮点数非常接近零 可以考虑0 要明确的是 我指的是算术下溢 http en wikipedia org wiki Arithmetic underflow
  • 如何在JdbcTemplate中执行多批量删除?

    我想一次删除多个数据库条目 仅当 3 个字段匹配 此处 姓名 电子邮件 年龄 时 才应删除每个条目 如果我只想删除单个属性 我会选择 String sql DELETE FROM persons WHERE email IN JdbcTem

随机推荐

  • 关于Unrecognized Windows Sockets error: 5: socket write error 错误

    最近有个需求是从A数据库读取数据导入到B数据库 demo的数据量也就几万条 但是遇到了一个非常罕见的问题 后端框架是mybatis plus spring boot 在insertBatch到数据库B时 没有立即报错 而是执行插入了几百条数
  • 小程序通过webView打开H5页面并传参(包含webView业务域名配置)、H5页面实现返回小程序并实现传参

    小程序内嵌webview实现跳转 传参 1 小程序通过webView打开H5页面并传参 2 H5接收小程序传参 H5返回小程序并实现传参 小程序接收H5传参 目录 一 小程序通过webView打开H5页面并传参 1 业务域名 2 在小程序中
  • (转)认识SAP SD销售模式之跨公司销售

    跨公司销售 销售订单的发货工厂对应的公司和销售组织对应的公司不同 比如 9801公司为销售性公司 9901为生产性的公司 当公司9801接到订单后 直接从9901公司发货 如果不通过跨公司销售 需要9801像9901公司下虚拟的采购订单 然
  • win10 下 Linux使用方法笔记

    最近想学习一下比特币源码 官方推荐是在Linux系统下学习 且推荐在win10 下的Linux系统进行编译运行 所以下面将学习过程记录一下 1 参考了这篇文章中的方法 进行安装WSL https www cnblogs com JettTa
  • agoda获取酒店数据

    最近改了改代码 正好解决了一些报错问题 更新出来 个别处会加蜜 数据库以及线程控制 from DBUtils PooledDB import PooledDB import requests import demjson import ti
  • 堆和栈的区别

    1 1内存分配方面 堆 一般由程序员分配释放 若程序员不释放 程序结束时可能由OS回收 注意它与数据结构中的堆是两回事 分配方式是类似于链表 可能用到的关键字如下 new malloc delete free等等 栈 由编译器 Compil
  • leetcode622-设计循环队列

    本题重点 1 选择合适的数据结构 2 针对选择的数据结构判断 空 和 满 这两点是不分先后次序的 在思考时应该被综合起来 事实上 无论我们选择链表还是数组 最终都能实现题中描述的 循环队列 的功能 只不过选择不同结构时 我们面临和需要解决的
  • 不是一个PDF文件或该文件已损坏

    之前用公司电脑打开PDF文档的时候 出现了这样的一种现象 就是提示格式错误 不是一个PDF文件或该文件已被损坏 有三种解决方法 1 有可能是电脑上自带的PDF阅读软件版本太低 出现了不兼容的现象 换个最新的PDF阅读器吧 我用了福昕阅读器很
  • 【死磕NIO】— 探索 SocketChannel 的核心原理

    大家好 我是大明哥 一个专注于 死磕 Java 系列创作的程序员 死磕 Java 系列为作者 chenssy 倾情打造的 Java 系列文章 深入分析 Java 相关技术核心原理及源码 死磕 Java https www cmsblogs
  • oracle不小心将表update修改了如何回滚

    oracle提供了一种闪回的方法 可以将某个时间的数据给还原回来 SELECT FROM T DIS EVENT RELATION TYPE AS OF TIMESTAMP TO TIMESTAMP 2023 08 08 15 31 00
  • python opencv 在线读取网络图片图像资源

    opencv在线读取网络图片图像资源 照例打开opencv3 3 0 python3 6官方文档 https docs opencv org master d8 dfe classcv 1 1VideoCapture html 详解 官方文
  • Adam和AdamW的区别

    Adam 与 Adamw的区别 一句话版本 Adamw 即 Adam weight decate 效果与 Adam L2正则化相同 但是计算效率更高 因为L2正则化需要在loss中加入正则项 之后再算梯度 最后在反向传播 而Adamw直接将
  • python框架和模型库_一个pytorch库,拥有最先进的架构,预训练模型和实时更新结果...

    PytorchInsight This is a pytorch lib with state of the art architectures pretrained models and real time updated results
  • first season last episode,Rachel finds out Ross likes her,what would she do???

    Scene Central Perk the whole gang is there Ross is showing pictures of his new baby boy Ben to the group Ross And here s
  • Flex布局

    之前一直都是使用position来定位块的位置 现在新学了一个比较主流的flex来定位块的位置 感觉确实比之前的好多了 现在总结下大概的用法 flex是把一个div分成主轴和交叉轴 其中主轴方向的定位有三个 1 flex direction
  • [OpenAirInterface实战-13] :OAI 基站配置文件详解

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 120791987 目录 第1章 基站配
  • Java中为什么数组没有实现Iterable接口,但可以使用foreach语句遍历?

    本质是转成fori形式的循环 上界是数组的size 直接上代码 package com finchina public class TstMain1 public static void main String args int ints
  • 西门子dcs系统组态手册下载_什么是PCS?----西门子PCS7篇

    PCS 7 PCS7是西门子的DCS系统 基于过程自动化 从传感器 执行器到控制器 再到上位机 自下而上形成完整的TIA 全集成自动化 架构 主要包括Step7 CFC SFC Simatic Net和WinCC以及PDM等软件 组态对象选
  • 华为OD题目: 租车骑绿道

    package com darling boot order od od19 import com google common base Strings import java util 租车骑绿道 p 题目 部门组织绿岛骑行团建活动 租用
  • ArrayBlockingQueue

    在java多线程操作中 BlockingQueue