Java中阻塞队列的使用

BlockingQueue(阻塞队列)详解 在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利。本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景。一旦获得了锁之后,如果队列为空,那么将阻塞;否则调用dequeue()出队一个元素。 阅读详情

在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利。本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景。

认识BlockingQueue阻塞队列,顾名思义,首先它是一个队列,而一个队列在数据结构中所起的作用大致如下图所示:

从上图我们可以很清楚看到,通过一个共享的队列,可以使得数据由队列的一端输入,从另外一端输出;

常用的队列主要有以下两种:(当然通过不同的实现方式,还可以延伸出很多不同类型的队列,DelayQueue就是其中的一种)

1. 先进先出(FIFO):先插入的队列的元素也最先出队列,类似于排队的功能。从某种程度上来说这种队列也体现了一种公平性。

2. 后进先出(LIFO):后插入队列的元素最先出队列,这种队列优先处理最近发生的事件。

多线程环境中,通过队列可以很容易实现数据共享,比如经典的“生产者”和“消费者”模型中,通过队列可以很便利地实现两者之间的数据共享。假设我们有若干生产者线程,另外又有若干个消费者线程。如果生产者线程需要把准备好的数据共享给消费者线程,利用队列的方式来传递数据,就可以很方便地解决他们之间的数据共享问题。但如果生产者和消费者在某个时间段内,万一发生数据处理速度不匹配的情况呢?理想情况下,如果生产者产出数据的速度大于消费者消费的速度,并且当生产出来的数据累积到一定程度的时候,那么生产者必须暂停等待一下(阻塞生产者线程),以便等待消费者线程把累积的数据处理完毕,反之亦然。然而,在concurrent包发布以前,在多线程环境下,我们每个程序员都必须去自己控制这些细节,尤其还要兼顾效率和线程安全,而这会给我们的程序带来不小的复杂度。好在此时,强大的concurrent包横空出世了,而他也给我们带来了强大的BlockingQueue。(在多线程领域:所谓阻塞,在某些情况下会挂起线程(即阻塞),一旦条件满足,被挂起的线程又会自动被唤醒)

下面两幅图演示了BlockingQueue的两个常见阻塞场景:

 

如上图所示:当队列中没有数据的情况下,消费者端的所有线程都会被自动阻塞(挂起),直到有数据放入队列。

 

如上图所示:当队列中填满数据的情况下,生产者端的所有线程都会被自动阻塞(挂起),直到队列中有空的位置,线程被自动唤醒。

这也是我们在多线程环境下,为什么需要BlockingQueue的原因。作为BlockingQueue的使用者,我们再也不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程,因为这一切BlockingQueue都给你一手包办了。既然BlockingQueue如此神通广大,让我们一起来见识下它的常用方法:

BlockingQueue的核心方法:

放入数据:

offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳, 则返回true,否则返回false

(本方法不阻塞当前执行方法的线程)

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

put(anObject):把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续.

获取数据:

poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,

取不到时返回null;

poll(long timeout, TimeUnit unit):从BlockingQueue取出一个队首的对象,如果在指定时间内,

队列一旦有数据可取,则立即返回队列中的数据。否则知道时间超时还没有数据可取,返回失败。

take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到

BlockingQueue有新的数据被加入;

drainTo():一次性从BlockingQueue获取所有可用的数据对象(还可以指定获取数据的个数),

通过该方法,可以提升获取数据效率;不需要多次分批加锁或释放锁。

常见BlockingQueue

 

在了解了BlockingQueue的基本功能后,让我们来看看BlockingQueue家庭大致有哪些成员?

BlockingQueue成员详细介绍

1. ArrayBlockingQueue

基于数组的阻塞队列实现,在ArrayBlockingQueue内部,维护了一个定长数组,以便缓存队列中的数据对象,这是一个常用的阻塞队列,除了一个定长数组外,ArrayBlockingQueue内部还保存着两个整形变量,分别标识着队列的头部和尾部在数组中的位置。

ArrayBlockingQueue在生产者放入数据和消费者获取数据,都是共用同一个锁对象,由此也意味着两者无法真正并行运行,这点尤其不同于LinkedBlockingQueue;按照实现原理来分析,ArrayBlockingQueue完全可以采用分离锁,从而实现生产者和消费者操作的完全并行运行。Doug Lea之所以没这样去做,也许是因为ArrayBlockingQueue的数据写入和获取操作已经足够轻巧,以至于引入独立的锁机制,除了给代码带来额外的复杂性外,其在性能上完全占不到任何便宜。 ArrayBlockingQueue和LinkedBlockingQueue间还有一个明显的不同之处在于,前者在插入或删除元素时不会产生或销毁任何额外的对象实例,而后者则会生成一个额外的Node对象。这在长时间内需要高效并发地处理大批量数据的系统中,其对于GC的影响还是存在一定的区别。而在创建ArrayBlockingQueue时,我们还可以控制对象的内部锁是否采用公平锁,默认采用非公平锁。

2. LinkedBlockingQueue

基于链表的阻塞队列,同ArrayListBlockingQueue类似,其内部也维持着一个数据缓冲队列(该队列由一个链表构成),当生产者往队列中放入一个数据时,队列会从生产者手中获取数据,并缓存在队列内部,而生产者立即返回;只有当队列缓冲区达到最大值缓存容量时(LinkedBlockingQueue可以通过构造函数指定该值),才会阻塞生产者队列,直到消费者从队列中消费掉一份数据,生产者线程会被唤醒,反之对于消费者这端的处理也基于同样的原理。而LinkedBlockingQueue之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。

作为开发者,我们需要注意的是,如果构造一个LinkedBlockingQueue对象,而没有指定其容量大小,LinkedBlockingQueue会默认一个类似无限大小的容量(Integer.MAX_VALUE),这样的话,如果生产者的速度一旦大于消费者的速度,也许还没有等到队列满阻塞产生,系统内存就有可能已被消耗殆尽了。

ArrayBlockingQueue和LinkedBlockingQueue是两个最普通也是最常用的阻塞队列,一般情况下,在处理多线程间的生产者消费者问题,使用这两个类足以。

下面的代码演示了如何使用BlockingQueue:

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.LinkedBlockingQueue;

/**

* @author jackyuj

*/

public class BlockingQueueTest {

public static void main(String[] args) throws InterruptedException {

// 声明一个容量为10的缓存队列

BlockingQueue<String> queue = new LinkedBlockingQueue<String>(10);

Producer producer1 = new Producer(queue);

Producer producer2 = new Producer(queue);

Producer producer3 = new Producer(queue);

Consumer consumer = new Consumer(queue);

// 借助Executors

ExecutorService service = Executors.newCachedThreadPool();

// 启动线程

service.execute(producer1);

service.execute(producer2);

service.execute(producer3);

service.execute(consumer);

// 执行10s

Thread.sleep(10 * 1000);

producer1.stop();

producer2.stop();

producer3.stop();

Thread.sleep(2000);

// 退出Executor

service.shutdown();

}

}

import java.util.Random;

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.TimeUnit;

/**

* 消费者线程

*

* @author jackyuj

*/

public class Consumer implements Runnable {

public Consumer(BlockingQueue<String> queue) {

this.queue = queue;

}

public void run() {

System.out.println("启动消费者线程!");

Random r = new Random();

boolean isRunning = true;

try {

while (isRunning) {

System.out.println("正从队列获取数据...");

String data = queue.poll(2, TimeUnit.SECONDS);

if (null != data) {

System.out.println("拿到数据:" + data);

System.out.println("正在消费数据:" + data);

Thread.sleep(r.nextInt(DEFAULT_RANGE_FOR_SLEEP));

} else {

// 超过2s还没数据,认为所有生产线程都已经退出,自动退出消费线程。

isRunning = false;

}

}

} catch (InterruptedException e) {

e.printStackTrace();

Thread.currentThread().interrupt();

} finally {

System.out.println("退出消费者线程!");

}

}

private BlockingQueue<String> queue;

private static final int DEFAULT_RANGE_FOR_SLEEP = 1000;

}

import java.util.Random;

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.atomic.AtomicInteger;

/**

* 生产者线程

*

* @author jackyuj

*/

public class Producer implements Runnable {

public Producer(BlockingQueue queue) {

this.queue = queue;

}

public void run() {

String data = null;

Random r = new Random();

System.out.println("启动生产者线程!");

try {

while (isRunning) {

System.out.println("正在生产数据...");

Thread.sleep(r.nextInt(DEFAULT_RANGE_FOR_SLEEP));

data = "data:" + count.incrementAndGet();

System.out.println("将数据:" + data + "放入队列...");

if (!queue.offer(data, 2, TimeUnit.SECONDS)) {

System.out.println("放入数据失败:" + data);

}

}

} catch (InterruptedException e) {

e.printStackTrace();

Thread.currentThread().interrupt();

} finally {

System.out.println("退出生产者线程!");

}

}

public void stop() {

isRunning = false;

}

private volatile boolean isRunning = true;

private BlockingQueue queue;

private static AtomicInteger count = new AtomicInteger();

private static final int DEFAULT_RANGE_FOR_SLEEP = 1000;

}

DelayQueue

DelayQueue中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素。DelayQueue是一个没有大小限制的队列,因此往队列中插入数据的操作(生产者)永远不会被阻塞,而只有获取数据的操作(消费者)才会被阻塞。

使用场景:

DelayQueue使用场景较少,但都相当巧妙,常见的例子比如使用一个DelayQueue来管理一个超时未响应的连接队列。

PriorityBlockingQueue

基于优先级的阻塞队列(优先级的判断通过构造函数传入的Compator对象来决定),但需要注意的是PriorityBlockingQueue并不会阻塞数据生产者,而只会在没有可消费的数据时,阻塞数据的消费者。因此使用的时候要特别注意,生产者生产数据的速度绝对不能快于消费者消费数据的速度,否则时间一长,会最终耗尽所有的可用堆内存空间。在实现PriorityBlockingQueue时,内部控制线程同步的锁采用的是公平锁。

SynchronousQueue

一种无缓冲的等待队列,类似于无中介的直接交易,有点像原始社会中的生产者和消费者,生产者拿着产品去集市销售给产品的最终消费者,而消费者必须亲自去集市找到所要商品的直接生产者,如果一方没有找到合适的目标,那么对不起,大家都在集市等待。相对于有缓冲的BlockingQueue来说,少了一个中间经销商的环节(缓冲区),如果有经销商,生产者直接把产品批发给经销商,而无需在意经销商最终会将这些产品卖给那些消费者,由于经销商可以库存一部分商品,因此相对于直接交易模式,总体来说采用中间经销商的模式会吞吐量高一些(可以批量买卖);但另一方面,又因为经销商的引入,使得产品从生产者到消费者中间增加了额外的交易环节,单个产品的及时响应性能可能会降低。

声明一个SynchronousQueue有两种不同的方式,它们之间有着不太一样的行为。公平模式和非公平模式的区别:

如果采用公平模式:SynchronousQueue会采用公平锁,并配合一个FIFO队列来阻塞多余的生产者和消费者,从而体系整体的公平策略;

但如果是非公平模式(SynchronousQueue默认):SynchronousQueue采用非公平锁,同时配合一个LIFO队列来管理多余的生产者和消费者,而后一种模式,如果生产者和消费者的处理速度有差距,则很容易出现饥渴的情况,即可能有某些生产者或者是消费者的数据永远都得不到处理。

小结

BlockingQueue不光实现了一个完整队列所具有的基本功能,同时在多线程环境下,他还自动管理了多线间的自动等待于唤醒功能,从而使得程序员可以忽略这些细节,关注更高级的功能。

一次详尽的问题定位记录:CPU使用率低负载高的排查过程 历史原因,当前有一个服务专门用于处理mq消息,mq使用的阿里云rocketmq,sdk版本1.2.6(2016年)。 随着业务的发展,该应用上的consumer越来越多,接近200+,导致该应用所在的ecs长时间load高,频繁报警。 现象分析 该应用所在的ecs服务器load长期飙高(该ecs上只有一个服务),但cpu、io、内存等资源利用率较低,系统负载参考下图: ECS配置:4核8G 物理cpu个数=4 单个物理CPU中核(core)的个数=1 单核多处理器 在系统负荷方面,多核CPU与多CPU效 阅读详情

相关推荐

【Java】阻塞队列

介绍阻塞队列的定义、种类、实现原理以及应用。

Creativity + Efficiency = Success 2032

六:抽象队列同步器AQS应用之BlockingQueue详解

目录 概要 队列类型 队列数据结构 ArrayBlockingQueue LinkedBlockingQueue DelayQueue BlockingQueue API 多线程生产者-消费者示例 并发编程脑图:https://www.processon.com/view/link/5d81dec7e4b04c14c4e7aac8 概要 BlockingQueue,是java.util.concurrent包提供的用于解决并发生产者 - 消费者问题的最有用的类,它的特性是在任意时刻只.

Xx__WangQi的博客 861

【JAVA多线程19】JAVA 阻塞队列原理

今天我们来讨论另外一类容器:阻塞队列。   非阻塞队列,比如PriorityQueue、LinkedList(LinkedList是双向链表,它实现了Dequeue接口)。   使用非阻塞队列的时候有一个很大问题就是:它不会对当前线程产生阻塞,那么在面对类似消费者-生产者的模型时,就必须额外地实现同步策略以及线程间唤醒策略,这个实现起来就非常麻烦。但是有了阻塞队列就不一样了,它会对当前线程产生...

dcm19920115的博客 2067

JAVA中的阻塞队列

一.什么是阻塞队列?阻塞队列是一个在队列基础上又支持了两个附加操作的队列。2个附加操作: 支持阻塞的插入方法:队列满时,队列会阻塞插入元素的线程,直到队列不满。 支持阻塞的移除方法:队列空时,获取元素的线程会等待队列变为非空。 二.阻塞队列的应用场景阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里取元素的线程。简而言之,阻塞队列是生产者用来存放元素、消费者获取元素

Fighting 6249

Java面试——阻塞队列

阻塞队列 定义:顾名思义,首先它是一个队列,而一个阻塞队列在数据结构中所起的作用大致如下 当阻塞队列是空时,从队列中获取元素的操作会被阻塞。 当阻塞队列是满时,往队列里添加元素的操作将会被阻塞。 这个是消息队列的底层原理 优点:可以不用管阻塞或者唤醒,阻塞队列会解决,可以很简单的写出一个生产者消费者模式。 ...

清风丨的博客 1767

无感健康监测的未来:毫米波雷达如何重新定义睡眠科技与居家养老

毫米波雷达技术正重新定义无感健康监测,特别是在睡眠科技与居家养老领域。通过精准监测呼吸、心率和体动,无需穿戴设备即可实现临床级精度。结合合宙Air700E开发板,构建了完整的远程看护解决方案,为老年人提供跌倒检测、异常报警等安全保障,同时保护用户隐私。

cake8的博客 570

Java阻塞队列

阻塞队列(Blocking Queue)是一种特殊的队列,因其为队列,因此遵循“先进先出”的原则,此外,其是一种线程安全的数据结构,具有以下两点特性:1. 当队列满时,继续入队列就会阻塞,直到有线程将元素从队列中取出2. 当队列空时,继续出队列就会阻塞,直到有线程向队列中插入元素阻塞队列常用于“生产者消费者模型什么是“生产者消费者模型”?“生产者消费者模式”是一种典型的开发模型,通过一个容器来解决生产者和消费者的强耦合问题向队列中添加元素的线程向队列中取出元素的线程。

2301_76161469的博客 2087

奈曼-皮尔逊准则

奈曼-皮尔逊准则 如果各个假设的先验概率P(Hi)(i=0,1)P(H_i)(i=0,1)P(Hi​)(i=0,1)已知,并且每种判决的代价函数已知,这时,可以用贝叶斯准则进行判决。 如果进一步假设正确判决不付出的代价,而错误判决代价相同,即c00=c11=0,c01=c10=1c_{00}=c_{11}=0,c_{01}=c_{10}=1c00​=c11​=0,c01​=c10​=1,这时可以用最小平均错误概率准则进行判决。 在不知道先验概率P(Hi)(i=0,1)P(H_i)(i=0,1)P(Hi​)(

little_soldier的专栏 1万+

【Java并发】阻塞队列 BlockingQueue

Java 的阻塞队列(Blocking Queue)是一种特殊的队列,主要用来阻塞队列的插入和获取操作,当队列满了的时候插入操作会被阻塞,直到队列有空位。当队列为空的时候获取操作会被阻塞,直到队列有值。本文对阻塞队列的概念和使用上做了体系化的总结和解析。

hrh的博客 3430

极化码理论及算法研究6-SCL、CA-SCL及matlab仿真

极化码译码算法5——SCL/CA-SCL译码算法系列目录1、引言2、串行抵消列表(SCL)译码算法2.1、路径度量PM 系列目录 (如要找其他内容,欢迎访问我的主页寻找) #前言 #极化码概述 #极化码定义 #极化码编码 #极化码译码 #5G标准中极化码的编译码概述 #5G标准中极化码的编码 #5G标准中极化码的译码 #总结 1、引言 在上一节中,介绍了经典的SC译码算法的理论原理以及其matlab仿真代码,SC译码算法具有较低的译码复杂度,但是由于每个译码的比特信息都依赖于前面所有的比特信息的译码结果,得

1万+

Agentic AI上下文工程架构终极指南:全面解决智能体理解问题

在开始架构设计前,我们需要先明确两个核心概念——Agentic AI和上下文工程。Agentic AI(智能体AI)是具备自主目标、环境交互、任务分解能力的AI系统。自主性:不需要人类逐步指令,能自己规划任务(比如“帮我订机票”→自动分解为“查航班→选座位→填信息→支付”);动态性:能根据环境变化调整行为(比如订机票时发现航班延误,自动改签到下一班);连续性:能记住历史交互(比如“上次你说喜欢靠窗位,这次帮你预留了”)。

AI开发架构师 1119

JAVA阻塞队列

JAVA阻塞队列

Excuse_lighttime的博客 1674

使用再生龙还原镜像文件到硬盘

1. 把制作好的再生龙光盘插入需要的电脑,开机按F4使用再生龙启动2. 选择默认的:Clonezailla live(Default settings,VGA 800*600),然后等待几分钟 3. 选择语言:简体中文 4. 选择不修改键盘映射 5. 选择使用再生龙          6. 选择硬盘/分区(存到/来自)镜像文件,此选项既可以制作镜像,也可以恢复镜像。 7. 使用本机的分区     ...

weixin_42168893的博客 1万+

Java阻塞队列原理

阻塞队列,关键字是阻塞,先理解阻塞的含义,阻塞队列中,线程阻塞有这样两种情况:当队列中没有数据的情况下,消费者端的所有线程都会被自动阻塞(挂起),直到有数据放入队列当队列中填满数据额情况下,生产者端的所有线程都会被自动阻塞(挂起),直到队列中有空的位置,线程被自动唤醒。

m0_73770897的博客 1631

海康视觉平台VisionMaster使用学习笔记(1)

双击图像源设置图像源的属性,像素格式分为Mono8和RDB24分别对应导入的图像是彩色还是黑白。打开相机驱动软件MVS,对连接的相机进行属性上的配置,先对相机的IP进行对应的设置。将自动触发的使能打开,保存配置好的相机属性,默认保存到用户集1中。点击MVS软件中的触发按钮,查看相机是否进行正常的触发拍照。打开VM软件添加一个图像源,选择图像源选项拖出图像源。回到VM软件中将选择相机选项选择到配置好参数的相机。取图方式也可以调整为相机取图,将图像源改为相机。双击相机进行连接后对相机的属性进行配置。

A567852的博客 1万+

AI大模型助力现金流精准预测案例详解

因为它的“注意力机制”能像“人一样思考”——比如,当预测“下周现金流”时,模型会重点关注“最近7天的销售数据”“未来7天的天气”“竞品是否有促销”这些关键因素,而忽略“去年同期的无关数据”。AI大模型不是“取代”财务人员,而是“赋能”他们——把财务人员从“重复的Excel操作”中解放出来,专注于“战略决策”(比如如何优化资金结构、如何提升资金利用率)。比如,“促销力度”这个特征,不是简单的“折扣率”,而是“折扣率×促销天数×覆盖SKU数量”,这样能更准确反映促销对现金流的影响。这些问题的核心,其实是。

AIGC应用创新大全的博客 1260

java阻塞队列的使用

1、介绍 阻塞队列,其实就是满足队列操作(先进先出)的一个数据集合,同时满足存取数据时的阻塞功能。 先进入阻塞队列的对象,会先被消费掉。 当阻塞队列已满时,生产者线程添加对象操作会被阻塞。 当阻塞队列已空时,消费者线程取出对象操作会被阻塞。 2、API分析 阻塞队列的直接接口为BlockingQueue,此接口内部定义了操作队列的各种方法。 BlockingQueue间接实现了Collection接口,所以阻塞队列其实就是一个集合,操作集合的各种方法,阻塞队列也满足。 核心方法 方法类型 抛

xiao_yu_gan的博客 1731

Android NDK/JNI面试题大全及参考答案(3万字长文)

是一套工具集合,它允许开发者为Android平台编写原生应用程序或者应用程序的部分模块。NDK 主要用于开发那些需要高性能计算的应用程序,例如游戏引擎、图像处理软件或音频/视频编码解码器等。通过使用 C 或 C++ 编写代码,开发者可以利用硬件加速功能,提高应用性能。NDK 提供了一系列工具来帮助开发者完成从源代码到可执行文件的整个过程,包括编译、链接、调试等功能。

大模型大数据攻城狮的专栏 1260

java中的阻塞队列

Java中的阻塞队列 一、什么是阻塞队列 所谓的阻塞队列,指的是:如果当前队列为空,那么获取元素的线程就会被阻塞,处于等待状态,直到队列变为非空;如果当前队列满的时候,添加元素的线程就会被阻塞,处于等待状态,直到队列有存储空间。阻塞队列是一个经典的生产者-消费者模式,生产者不停的往队列里面添加元素,消费者不停的从队列消费元素。阻塞队列就是实现生产者-消费者模式借助的第三方,很多时候,我们找到这

牛奋lch 1210

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Java中的阻塞队列

详解 Java 7 大阻塞队列,剖析 ArrayBlockingQueue 等核心类型特性,深入解读实现原理,并结合生产者 - 消费者模型、线程池应用场景,助你掌握多线程开发关键技术。

JIGUANGDI 784

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

java之阻塞队列(BlockingQueue)

java之阻塞队列一、阻塞队列概念二、阻塞队列的好处三、阻塞队列种类四、BlockingQueue的核心方法五、示例代码1.使用SychronousQueue队列2.传统版生产者消费者模式3.阻塞队列版(以ArrayBlockingQueue为例)生产者消费者模式 一、阻塞队列概念 阻塞队列,顾名思义,首先它是一个队列(先进先出),而一个阻塞队列在数据结构所起到的作用大致如下图: 线程1往阻塞队列中添加元素,而线程2从阻塞队列中移除元素 当阻塞队列是空是,从队列中获取元素的操作会被阻塞 当阻塞队列是满时

weixin_43824267的博客 3007

阻塞队列(JAVA)

阻塞队列是一种特殊的队列,也遵守 "先进先出" 的原则。阻塞队列能是一种JAVA标准库中已经实现了阻塞队列,我们可以直接进行使用。 BlockingQueue是一个接口,阻塞队列也和普通队列一样有两种实现方式:数组和链表。 注:创建阻塞队列时需要传入队列的长度参数。

2302_76339343的博客 1721
上一篇: Java 求1-100以内的所有素数,判断一个数是不是素数
下一篇: atomic包的原理及分析
java1856905
博客等级 码龄8年 100粉丝 249原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值