Java 入门指南:Java 并发编程 —— 并发容器 LinkedBlockingQueue

news2024/11/14 5:52:22

BlockingQueue

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

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

常用的实现类有:

  • ArrayBlockingQueue:并发容器 ArrayBlockingQueue 详解
  • LinkedBlockingQueue
  • PriorityBlockingQueue:并发容器 PriorityBlockingQueue 详解
  • SynchronousQueue:并发容器 SynchronousQueue 详解
  • LinkedBlockingDeque: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) 带有超时时间的方法。

LinkedBlockingQueue

LinkedBlockingQueue 是 Java 中的一个线程安全的阻塞队列实现。实现了 BlockingQueue 接口,并使用链表作为底层数据结构,可以用于在生产者和消费者之间进行线程安全的数据传输。

特点
  1. 队列容量:LinkedBlockingQueue 可以选择指定容量,也可以不指定容量(默认为 Integer.MAX_VALUE),即可以是有界队列或无界队列

  2. 先进先出(FIFO):队列遵循先进先出的原则,即先入队的元素会先出队。

  3. 阻塞操作:当队列为空时,消费者线程调用 take() 方法将被阻塞,直到有元素可用;当队列满时,生产者线程调用 put() 方法将被阻塞,直到队列有空间。

  4. 链表实现:LinkedBlockingQueue 使用链表作为内部实现,这个链表由一系列的节点组成,每个节点都包含了一个元素以及指向下一个节点的引用。队列的头部和尾部都维护了对这些节点的引用,以便进行高效的入队和出队操作。

  5. 线程安全LinkedBlockingQueue内部通过锁机制确保了线程安全,所有公共方法都是原子的。

使用场景
  1. 生产者-消费者模式LinkedBlockingQueue 可以作为生产者和消费者之间的缓冲区,生产者将产品放入队列,消费者从队列中获取产品进行处理。

  2. 线程池:线程池中的任务队列一般使用 LinkedBlockingQueue 实现,线程池根据需要动态地创建和销毁线程,将任务放入队列中,让线程从队列中获取任务进行处理。

  3. 任务调度LinkedBlockingQueue 可以作为任务调度的工具,将需要执行的任务放入队列中,再由任务调度器从队列中获取任务并执行。

构造方法
  1. 创建初始容量为 Integer.MAX_VALUE无界队列
LinkedBlockingQueue()
  1. 创建指定容量的有界队列。如果队列已满,入队操作将会阻塞,直到队列中有空间。
LinkedBlockingQueue(int capacity)
  1. LinkedBlockingQueue(Collection<? extends E> c): 创建队列,并将集合中元素按照顺序加入队列中,将队列大小初始化为元素的个数。
LinkedBlockingQueue(Collection<? extends E> collection)
LinkedBlockingQueue 使用示例

LinkedBlockingQueue 是 Java 并发包 java.util.concurrent 中的一个线程安全的阻塞队列实现,它基于链表结构存储数据,并且提供了阻塞操作,非常适合用于多线程环境下的数据交换和同步控制。

下面是一个使用 LinkedBlockingQueue 的简单示例,展示如何实现一个基本的生产者-消费者模型:

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class LinkedBlockingQueueExample {

    public static void main(String[] args) {
        // 创建一个最大容量为 10 的 LinkedBlockingQueue
        LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(10);

        // 创建生产者线程
        Thread producerThread = new Thread(() -> {
            try {
                for (int i = 0; i < 20; i++) {
                    String item = "Item " + i;
                    System.out.println("Producing: " + item);
                    // put 方法会在队列满的时候阻塞当前线程,直到有空间可用
                    queue.put(item);
                    TimeUnit.MILLISECONDS.sleep(200); // 模拟生产数据的时间间隔
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("Producer was interrupted");
            }
        });

        // 创建消费者线程
        Thread consumerThread = new Thread(() -> {
            try {
                for (int i = 0; i < 20; i++) {
                    String item = queue.take(); // take 方法会在队列空的时候阻塞当前线程,直到有数据可用
                    System.out.println("Consuming: " + item);
                    TimeUnit.MILLISECONDS.sleep(500); // 模拟消费数据的时间间隔
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("Consumer was interrupted");
            }
        });

        // 启动线程
        producerThread.start();
        consumerThread.start();

        // 等待线程结束
        try {
            producerThread.join();
            consumerThread.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

在这个例子中,我们创建了一个最大容量为 10 的 LinkedBlockingQueue。生产者线程会不断地尝试向队列中放入数据,而消费者线程则不断地尝试从中取出数据。当队列已满时,put 方法会让生产者线程等待,直到有空间可用;当队列为空时,take 方法会让消费者线程等待,直到有数据可用。这种机制保证了生产者和消费者之间的同步。

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

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

相关文章

JavaEE---Spring MVC(4)

MVC学习小案例1 在这里我们要实现一个计算器的功能 在这之前,先解决一个bug! 写好代码之后开始运行,运行发现不对,sum计算不出来,然后我百思不得其解, 1.对着后端代码一顿输出,还是没觉得有问题. 2.对着前端代码一顿输出,也没看出任何问题 3.是不是我前后端交互出错了呢?查找…

Python案例 | 四阶龙格库塔法简介

1.引言 在数值分析中&#xff0c;龙格-库塔法&#xff08;Runge-Kutta methods&#xff09;是用于非线性常微分方程的解的重要的一类隐式或显式迭代法。这些技术由数学家卡尔龙格和马丁威尔海姆库塔于1900年左右发明。 龙格-库塔(Runge-Kutta)方法是一种在工程上应用广泛的高…

工厂验收(FAT)和现场验收(SAT)的含义

工厂验收&#xff08;Factory Acceptance Test&#xff0c;FAT&#xff09;和现场验收&#xff08;Site Acceptance Test&#xff0c;SAT&#xff09;是在工程领域中常见的术语&#xff0c;用于确保设备在制造商及用户之间达成一致的验收标准&#xff0c;保证设备能够正常、安全…

【图灵完备 Turing Complete】游戏经验攻略分享 Part.2 算术运算

算术运算部分算是开始有难度了。 前几关按照自己思路来&#xff0c;二进制速算应该没问题。 画真值表&#xff0c;卡诺图&#xff0c;推表达式。 下面几关&#xff0c;几个输出信号分开来看&#xff0c;有三个输出就画三个卡诺图&#xff0c;有几个画几个&#xff0c;分而治之。…

Shadow Dom 是什么

概念 官方&#xff1a;https://developer.mozilla.org/zh-CN/docs/Web/API/Web_components/Using_shadow_DOM 核心&#xff1a;影子 DOM&#xff08;Shadow DOM&#xff09;允许你将一个 DOM 树附加到一个元素上&#xff0c;并且使该树的内部对于在页面中运行的 JavaScript 和…

Java笔试面试题AI答之正则表达式(3)

文章目录 13. 简述Java String支持哪几种使用正则表达式的方法&#xff1f;14. 请列举常见校验数字的表达式 &#xff1f;15. 请列举常见校验字符的表达式 &#xff1f;1. 汉字2. 英文和数字3. 特定长度的字符串4. 由26个英文字母组成的字符串5. 由数字和26个英文字母组成的字符…

JVM面试(五)垃圾回收机制和算法

概述 了解Java虚拟机的垃圾回收机制&#xff08;Garbage Collection&#xff0c;简称GC&#xff09;&#xff0c;我们也要像其作者John McCarthy一样&#xff0c;思考一下三个问题&#xff1a; 哪些内存需要回收&#xff1f;什么时候回收&#xff1f;如何回收&#xff1f; 虽…

pytorch+深度学习实现图像的神经风格迁移

本文的完整代码和部署教程已上传至本人的GitHub仓库&#xff0c;欢迎各位朋友批评指正&#xff01; 1.各代码文件详解 1.1 train.py train.py 文件负责训练神经风格迁移模型。 加载内容和风格图片&#xff1a;使用 utils.load_image 函数加载并预处理内容和风格图片。初始化…

网络攻击全解析:主动、被动与钓鱼式攻击的深度剖析

在当今这个互联网高度普及与深度融合的时代&#xff0c;网络攻击&#xff0c;这一赛博空间的隐形威胁&#xff0c;正以前所未有的频率和复杂度挑战着网络安全乃至国家安全的底线。为了更好地理解并防范这些威胁&#xff0c;本文将深入剖析网络攻击的主要类型——主动攻击、被动…

程序设计基础

一、程序 1.什么是程序&#xff1f; 程序可以看作是对一系列动作的执行过程的描述。 计算机程序是指为了得到某种结果而由计算机等具有信息处理能力的装置执行的代码化指令序列。 程序的几个性质&#xff1a; ● 目的性 ● 分步性 ● 有限性 ● 可操作性 ● 有序性 2…

Splasthop 安全远程访问帮助企业对抗 Cobalt Strike 载荷网络攻击

一、背景 根据 FreeBuf&#xff08;标题为&#xff1a;潜藏系统2个月未被发现&#xff0c;新型网络攻击瞄准中国高价值目标&#xff09;和 The Hacker News&#xff08;标题为&#xff1a;New Cyberattack Targets Chinese-Speaking Businesses with Cobalt Strike Payloads&a…

农产品自主供销系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;农产品管理&#xff0c;资讯信息管理&#xff0c;订单管理&#xff0c;资讯回复管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;农产品&#xff0c;购物车&#xff0c;我的 开发系统&#…

接口自动化测试学习 —— Mock服务实现

1.Mock实现原理和实现机制 在某些时候&#xff0c;后端在开发接口的时候&#xff0c;处理逻辑非常复杂&#xff0c;在测试的时候&#xff0c;后端在未完成接口的情况下该如何去测试呢&#xff1f; 我们需要测试&#xff0c;但是有些请求又需要修改一下参数&#xff0c;或者改变…

说明书keithley2420吉时利2410数字源表

说明书keithley2420吉时利2410数字源表 产品概述 Keithley 2420 高压源表是一款 60W 仪器&#xff0c;设计用于提供和测量 5V&#xff08;源&#xff09;和 1V&#xff08;测量&#xff09;至 60V 的电压和 100pA 至 3A 的电流。2420 型的生产测试应用包括必须在更高电流水平下…

微信和苹果叫板的资本

这两天&#xff0c;关于苹果用户还能不能使用微信这么一个新闻炒得沸沸扬扬的。其实&#xff0c;在很多年前我就说过&#xff0c;腾讯和苹果必有一战。那么这一战到了今天终于到来了。 原因其实也很简单。这个事件的背后&#xff0c;并不是简单的腾讯和苹果彼此之间抽成争夺的问…

pr瘦脸怎么操作?

相信大家平时在拍摄自己的日常生活的时候&#xff0c;通常为了保证视频的清晰度往往都会选择原相机进行拍摄&#xff0c;原相机拍摄自然就会清清楚楚的将我们的真实展现出来&#xff0c;特别是脸部肥大~那么&#xff0c;这么大的一张脸这么可以瘦下去呢&#xff1f;其实使用PR软…

glsl着色器学习(五)

接下来是创建buffer&#xff0c;设置顶点位置&#xff0c;法线&#xff0c;顶点索引等。 const cubeVertexPositions new Float32Array([1, 1, -1,1, 1, 1, 1, -1, 1, 1, -1, -1,-1, 1, 1, -1, 1, -1,-1, -1, -1,-1, -1, 1,-1, 1, 1,1, 1, 1,1, 1, -1,-1, 1, -1,-1, -1, -1,1…

2024.9.3C++

自行实现Mystring类 #include <iostream> #include <cstring> using namespace std;class mystring { public:mystring(){len 0;str nullptr;}mystring(const char* s){len strlen(s);str new char[len 1];strcpy(str, s);}mystring(const mystring& othe…

短时相关+FFT捕获方法的MATLAB仿真

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 短时相关FFT捕获方法的MATLAB仿真 前言短时相关FFT捕获相关原理1、频偏引起的相关损失2、扇贝损失 MATLAB程序获取完整程序 前言 对于算法类的工程&#xff0c;FPGA设计&…

pandas数据处理库使用

文章目录 链接: [原文章链接](https://mp.weixin.qq.com/s?__bizMzkzNjI3ODkyNQ&tempkeyMTI4Nl8zM3FHVFU1NDRDL0p2SkplRTVidmhiNmh1ZWF3YXkwY3VYZlZNaWx0MXowdThFbVRUVEFEdEs5YlU2SUJLcmtXTHZpbnFmR2V6SG1rbGJyd01zYnRkdURWa1ZvNGtIU1piWDd5RFA4OUxkNmlaVmZ1QVpEd2tWR25IR…