Java 入门指南:Java 并发编程 —— 并发容器 BlockingDeque、LinkedBlockingDeque

news2024/9/21 0:27:05

BlockingQueue

BlockingQueue 是Java并发包(java.util.concurrent)中提供的一个阻塞队列接口,它继承自 Queue 接口。

BlockingQueue 中的元素采用 FIFO 的原则,支持多线程环境并发访问,提供了阻塞读取和写入的操作,当前线程在队列满或空的情况下会被阻塞,直到被唤醒或超时。

常用的实现类有:

  • ArrayBlockingQueue:并发容器 ArrayBlockingQueue 详解
  • LinkedBlockingQueue:并发容器 LinkedBlockingQueue 详解
  • PriorityBlockingQueue:并发容器 PriorityBlockingQueue 详解
  • SynchronousQueue:并发容器 SynchronousQueue 详解
  • LinkedBlockingDeque
    等类,它们的实现方式各有不同。
适用场景

BlockingQueue 通常用于一个线程生产对象,而另外一个线程消费这些对象的场景。

![[BlockingQueue Model.png]]

一个线程将会持续生产新对象并将其插入到队列之中,直到队列达到它所能容纳的临界点

如果该阻塞队列到达了其临界点,生产者线程将会在往里边插入新对象时发生阻塞。它会一直处于阻塞之中,直到消费者线程从队列中拿走一个对象。

消费者线程将会一直从该阻塞队列中拿出对象。如果消费线程尝试去从一个空的队列中提取对象的话,这个消费线程将会处于阻塞之中,直到一个生产线程把一个对象丢进队列。

常用方法
  1. put(E e):将元素 e 插入到队列中,如果队列已满,则会阻塞当前线程,直到队列有空闲空间

  2. offer(E e):将元素 e 插入到队列中,如果队列已满,则返回 false。

  3. offer(E element, long timeout, TimeUnit unit) 方法是 BlockingQueue:在指定的时间内将元素添加到队列中。

    • timeout:超时时间,表示在指定的时间内等待队列空间可用。如果超过指定的时间仍然无法将元素添加到队列中,将返回 false。

    • unit:超时时间的单位。

  4. take():移除并返回队列头部的元素,如果队列为空,则会阻塞当前线程,直到队列有元素

  5. poll():移除并返回队列头部的元素,如果队列为空,则返回 null

  6. poll(long timeout, TimeUnit unit):在指定的时间内从队列中检索并移除元素。返回移除的元素。如果超过指定的时间仍然没有可用的元素,将返回 null。

  7. peek():返回队列头部的元素,但不会移除。如果队列为空,则返回null

  8. size():返回队列中元素的数量

  9. isEmpty():判断队列是否为空,为空返回 true,否则返回 false

  10. isFull():判断队列是否已满,已满返回 true,否则返回 false

  11. clear():清空队列中的所有元素

行为抛异常返回特定值阻塞超时
插入add(o)offer(o)put(o)offer(o, timeout, timeunit)
移除remove()poll()take()poll(timeout, timeunit)
检查element()peek()
  • 抛异常: 如果试图的操作无法立即执行,抛一个异常。

  • 特定值: 如果试图的操作无法立即执行,返回 true / false / null)。

  • 阻塞: 如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行。

  • 超时: 如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行,但等待时间不会超过给定值。返回一个特定值以告知该操作是否成功(典型的是 true / false)。

若向 BlockingQueue 中插入 null,将会抛出 NullPointerException

死锁问题

需要注意的是,在使用 BlockingQueue 时要注意防止死锁的问题:

  • 在队列满之后调用 offer() 方法插入元素会返回false,此时不能直接调用put()方法,因为在插入之前还需要获取其它资源,如果在获取资源时一直阻塞在这里,就会发生死锁。

  • 为了防止死锁的问题,建议使用 offer(E e, long timeout, TimeUnit unit)poll(long timeout, TimeUnit unit) 带有超时时间的方法。

BlockingDeque

JUC 包里的 BlockingDeque 接口表示一个线程安放入和提取实例的双端队列,继承自 BlockingQueue

BlockingDeque 是一个双端队列,在不能够插入元素时,它将阻塞住试图插入元素的线程;在不能够提取元素时,它将阻塞住试图提取的线程。

BlockingDeque 适用于在线程中一个队列既充当生产者又充当消费者的情况。

如果生产者线程需要在队列的两端都可以插入数据,消费者线程需要在队列的两端都可以移除数据,这个时候也可以使用 BlockingDeque

![[BlockingDeque Model.png]]

主要方法
  1. addFirst(E element):将指定的元素插入到双端队列的头部。如果插入操作成功,则将返回 true;否则,将抛出异常。

  2. addLast(E element):将指定的元素插入到双端队列的尾部。如果插入操作成功,则将返回 true;否则,将抛出异常。

  3. offerFirst(E element):将指定的元素插入到双端队列的头部。如果插入操作成功,则将返回 true;否则,将返回 false。

  4. offerLast(E element):将指定的元素插入到双端队列的尾部。如果插入操作成功,则将返回 true;否则,将返回 false。

  5. removeFirst():移除并返回双端队列的头部元素。如果队列为空,则将抛出异常。

  6. removeLast():移除并返回双端队列的尾部元素。如果队列为空,则将抛出异常。

  7. pollFirst():移除并返回双端队列的头部元素。如果队列为空,则返回 null。

  8. pollLast():移除并返回双端队列的尾部元素。如果队列为空,则返回 null。

  9. getFirst():返回双端队列的头部元素,但不会移除它。如果队列为空,则将抛出异常。

  10. getLast():返回双端队列的尾部元素,但不会移除它。如果队列为空,则将抛出异常。

  11. peekFirst():返回双端队列的头部元素,但不会移除它。如果队列为空,则返回 null。

  12. peekLast():返回双端队列的尾部元素,但不会移除它。如果队列为空,则返回 null。

  13. putFirst(E element): 将元素插入双端队列的头部,如果队列已满则阻塞等待空间可用。

  14. putLast(E element): 将元素插入双端队列的尾部,如果队列已满则阻塞等待空间可用。

  15. takeFirst(): 移除并返回双端队列的头部元素,如果队列为空则阻塞等待元素可用。

  16. takeLast(): 移除并返回双端队列的尾部元素,如果队列为空则阻塞等待元素可用。

![[BlockingDeque Methods.png]]

LinkedBlockingDeque

LinkedBlockingDeque 是 Java 中的一个具体实现类,它是一个由链表结构组成的双向阻塞队列。它继承自 AbstractQueue 类并实现了 BlockingDeque 接口。

特点
  1. 链表结构:LinkedBlockingDeque 内部使用链表来存储元素,因此它的大小可以根据需要动态扩容

  2. 容量可选:可以选择初始化 LinkedBlockingDeque 时指定容量大小,如果不指定,则默认为 Integer.MAX_VALUE。当元素数量达到容量上限时,后续插入操作将会被阻塞,直到有其他线程对队列进行取出操作。

  3. 双端队列:LinkedBlockingDeque 具有双端插入和双端取出的特性,即既可以在队首插入和取出元素,也可以在队尾插入和取出元素。

  4. 阻塞操作:当调用插入操作(如 addFirst(), addLast(), putFirst(), putLast()) 或取出操作(如 takeFirst(), takeLast(), pollFirst(), pollLast()) 时,如果队列已满或为空,线程将会被阻塞,直到有其他线程进行相应的取出或插入操作。

  5. 非线程安全:LinkedBlockingDeque 不是线程安全的,如果在多个线程中同时进行插入、取出操作,需要进行外部同步控制或使用 JUC 包中的相关线程安全类。

构造方法
  1. 创建一个没有指定容量的 LinkedBlockingDeque 对象。该队列可以根据需要动态调整大小。
LinkedBlockingDeque()
  1. 创建一个具有指定容量的 LinkedBlockingDeque 对象。该队列的容量是固定的,不能更改
LinkedBlockingDeque(int capacity)
  1. 创建一个具有初始元素集合的 LinkedBlockingDeque 对象。初始元素集合会按照集合的迭代器顺序依次添加到队列中,容量大小为元素个数。
LinkedBlockingDeque(Collection<? extends E> collection)
LinkedBlockingDeque 使用示例

下面是一个简单的示例,展示如何使用 LinkedBlockingDeque

import java.util.concurrent.LinkedBlockingDeque;

public class BlockingDequeExample {

    public static void main(String[] args) throws InterruptedException {
        // 创建一个 LinkedBlockingDeque 实例
        LinkedBlockingDeque<String> deque = new LinkedBlockingDeque<>(10);

        // 向队列中添加元素
        deque.offerFirst("one");
        deque.offerLast("two");

        // 输出队列内容
        System.out.println("Initial Deque: " + deque);

        // 从队列中移除元素
        String firstElement = deque.pollFirst();
        String lastElement = deque.pollLast();

        // 输出移除后的队列内容
        System.out.println("Deque after removal: " + deque);

        // 检查队列中的元素
        System.out.println("First element: " + firstElement);
        System.out.println("Last element: " + lastElement);

        // 使用阻塞方法添加元素
        deque.putFirst("three");
        deque.putLast("four");

        // 输出添加后的队列内容
        System.out.println("Deque after adding elements: " + deque);

        // 使用阻塞方法移除元素
        String blockedFirstElement = deque.takeFirst();
        String blockedLastElement = deque.takeLast();

        // 输出移除后的队列内容
        System.out.println("Deque after blocked removal: " + deque);

        // 检查阻塞移除的元素
        System.out.println("Blocked First element: " + blockedFirstElement);
        System.out.println("Blocked Last element: " + blockedLastElement);
    }
}

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

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

相关文章

Jenkins构建CI/CD

CI/CD 软件开发的连续方法基于自动执行脚本&#xff0c;以最大限度地减少在开发应用程序时引入错误的可能性。从新代码的开发到部署&#xff0c;它们需要较少的人为干预甚至根本不需要干预。 它涉及在每次小迭代中不断构建&#xff0c;测试和部署代码更改&#xff0c;从而减少…

多线程 | synchronized的简单使用

synchronized 关键字是 Java 中解决并发问题的一种常用方法&#xff0c;也是最简单的一种方法&#xff0c;其作用有三个: &#xff08;1&#xff09;互斥性&#xff1a;确保线程互斥的访问同步代码 &#xff08;2&#xff09;可见性&#xff1a;保证共享变量的修改能够及时可见…

UOS系统通过Remmina远程windows系统桌面

windows系统之间可以互相进行远程桌面连接&#xff0c;那么UOS系统是否可以远程到windows系统桌面呢&#xff1f;请见下面的文章。 下载安装Remmina软件 首先我们需要在UOS系统上面找到应用商店&#xff0c;下载并安装一个Remmina软件 windows系统开启允许远程桌面连接 wind…

记录ssl epoll的tcp socket服务端在客户端断开时崩溃的问题

文章目录 当客户端关闭后&#xff0c;Epoll 的 TCP socket 服务端会收到两次断开事件可能有以下原因及解决方法&#xff1a;原因分析解决方法 问题ssl socket服务端代码出错现象第一次尝试修改正确改法附上客户端代码 记录ssl epoll的tcp socket服务端在客户端断开时接收到多次…

聚铭网络入选“2024年南京市工程研究中心”认定名单

为深入实施创新驱动发展战略&#xff0c;因地制宜发展新质生产力充分发挥工程研究中心对推进产业强市的重要支撑作用&#xff0c;根据《南京市工程研究中心管理办法》&#xff0c;南京市发展和改革委员会于2024年5月组织开展了本年度南京市工程研究中心遴选工作。经企业申报、各…

编译安装调试 scaLapack 和 openmpi 以及 lapack

编译安装调试 scaLapack /home/hipper/ex_scalapack/ mkdir ./lapack mkdir -p ./lapack/local/lib mkdir ./openmpi mkdir ./scalapack 1&#xff0c;编译安装 Lapack 下载代码&#xff1a; cd lapack wget https://github.com/Reference-LAPACK/lapack/archive/refs/tags/…

[全网首发]2024国赛数学建模ABCE题完整思路+py(matlab)代码+成品论文参考+持续更新

AB题详细思路(含问题一问题二模型) CE题问题一代码思路已经写好[pythonmatlab两种都会更新 需要完整版的看这里&#xff1a; 点击链接加入群聊【2024数学建模国赛资料汇总】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&klZncBILk30DuPRI1Bd8X-3Djv7ZVZyAv&…

【非零段划分 / 2】

题目 思路 第一种思路&#xff1a;按照表面题意&#xff0c;枚举p&#xff0c;处理数组后进行计数&#xff1a; 复杂度 ∈ O ( n ⋅ m ) 复杂度 \in O(n \cdot m) 复杂度∈O(n⋅m) 第二种思路&#xff1a;把数组看成一个二维的山形图&#xff0c;先将相邻的水平线段转化成点…

Java核心知识体系-并发与多线程:线程基础

1 先导 Java线程基础主要包含如下知识点&#xff0c;相信我们再面试的过程中&#xff0c;经常会遇到类似的提问。 1、线程有哪几种状态? 线程之间如何转变&#xff1f; 2、线程有哪几种实现方式? 各优缺点&#xff1f; 3、线程的基本操作&#xff08;线程管理机制&#xff…

数据资产入表元年,企业如何抓住数据资产增值的机遇?

近年来&#xff0c;政府将数据要素纳入了经济发展的重要指示性文件当中&#xff0c;希望利用数据驱动。《全国数据资源调查报告&#xff08;2023年&#xff09;》显示&#xff0c;2024年以来不少地方纷纷成立“数据集团”&#xff0c;加快盘活数据资产。作为数字经济时代的首要…

Java | Leetcode Java题解之第389题找不同

题目&#xff1a; 题解&#xff1a; class Solution {public char findTheDifference(String s, String t) {int ret 0;for (int i 0; i < s.length(); i) {ret ^ s.charAt(i);}for (int i 0; i < t.length(); i) {ret ^ t.charAt(i);}return (char) ret;} }

编写Dockerfile第二版

目标 更快的构建速度 更小的Docker镜像大小 更少的Docker镜像层 充分利用镜像缓存 增加Dockerfile可读性 让Docker容器使用起来更简单 总结 编写.dockerignore文件 容器只运行单个应用 将多个RUN指令合并为一个 基础镜像的标签不要用latest 每个RUN指令后删除多余文…

leetcode172. 阶乘后的零,遍历每个因数中5的个数

leetcode172. 阶乘后的零 给定一个整数 n &#xff0c;返回 n! 结果中尾随零的数量。 提示 n! n * (n - 1) * (n - 2) * … * 3 * 2 * 1 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;0 解释&#xff1a;3! 6 &#xff0c;不含尾随 0 示例 2&#xff1a; 输…

第八届控制工程与先进算法国际论坛(IWCEAA 2024)

重要信息 会议大会官网&#xff1a;www.iwaace.cn&#xff08;点击进一步了解&#xff09; 二轮截稿时间&#xff1a;2024年09月27日 录用通知时间&#xff1a;投稿后7个工作日 收录检索类型&#xff1a;IEEE Xplore, EI, Scopus 大会介绍 第八届控制工程与先进算法国际论…

python 交互模式怎么切换目录

假如要用交互界面调用一个.py文件&#xff1a; &#xff08;1&#xff09;用cmd界面定位到文件位置&#xff0c;如cd Desktop/data/ #进入desktop下data目录。 &#xff08;2&#xff09;接着打开python&#xff08;输入python&#xff09; 调用os &#xff08;1&#xff0…

3.js - modelPosition.z = sin((modelPosition.x+uTime)*10.0)*0.05;

哈 1、完整的动态波纹效果吧 main.js import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls// 顶点着色器 import basicVertexShader from ./shader/11-01/raw/vertex.glsl?raw // 片元着色器 import basicFragmentShad…

python OpenGL绘制正八面体代码

学习OpenGL过程中&#xff0c;先从绘制三角形开始逐渐对Opengl有一些了解&#xff0c;到现在进阶到绘制立方体。通过借鉴网友绘制六面体得到灵感&#xff0c;改了一下他的代码成功绘制出正八面体。不管是绘制三角形还是绘制立方体&#xff0c;对于空间坐标系要相当熟悉&#xf…

苍穹外卖项目前端DAY03

前端DAY03 1、套餐管理 1.1、套餐分页查询 1.1.1、需求分析和接口设计 产品原型&#xff1a; 业务规则&#xff1a; 根据页码展示套餐信息每页展示10条数据分页查询时可以根据需要&#xff0c;输入套餐名称、套餐分类、售卖状态进行查询 接口设计&#xff1a; 套餐分页查…

如何使用电商API接口?(淘宝|京东商品详情数据接口)

一、了解电商API接口&#xff1a; 如今&#xff0c;在电商市场中&#xff0c;电商API接口的广泛应用极大地提高了电商行业的工作效率&#xff0c;使得商家能够灵活集成多种服务&#xff0c;高效优化业务流程。 当前&#xff0c;电商平台中的多种业务都可以通过使用API接口来做…

Tomato靶场渗透测试

1.扫描靶机地址 可以使用nmap进行扫描 由于我这已经知道靶机地址 这里就不扫描了 2.打开网站 3.进行目录扫描 dirb http&#xff1a;//172.16.1.113 发现有一个antibot_image目录 4.访问这个目录 可以看到有一个info.php 5.查看页面源代码 可以发现可以进行get传参 6.…