网站首页 > java教程 正文
前言:
LinkedBlockingQueue 和 ConcurrentLinkedQueue 是 Java 高并发场景中最常使用的队列。高并发场景中经常用的数据结构,但它们之间仍有细微的特征和行为差异。下面说一下两者及区别。
LinkedBlockingQueue
首先 LinkedBlockingQueue 是一个 “可选且有界” 的阻塞队列实现,你可以根据需要指定队列的大小。 接下来,我将创建一个LinkedBlockingQueue,它最多可以包含100个元素:
BlockingQueue<Integer> boundedQueue = new LinkedBlockingQueue<>(100);
也可以通过不指定大小,来创建一个无界的 LinkedBlockingQueue:
BlockingQueue<Integer> unboundedQueue = new LinkedBlockingQueue<>();
无界队列表示在创建时未指定队列的大小。因此,队列可以随着元素的添加而动态增长。但是,如果没有剩余内存,则队列将抛出 java.lang.OutOfMemory 错误。
可以从现有的集合来创建 LinkedBlockingQueue:
LinkedBlockingQueue 实现了BlockingQueue接口,该接口为它提供了阻塞性质。
阻塞队列表示如果访问线程已满(当队列有界时)或变为空,则队列将阻塞该线程。如果队列已满,则添加新元素将阻塞访问线程,除非新元素有可用空间。类似地,如果队列为空,则访问元素会阻塞调用线程:
ExecutorService executorService = Executors.newFixedThreadPool(1);
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
executorService.submit(() -> {
try {
queue.take();
}
catch (InterruptedException e) {
// exception handling
}
});
在上面的代码片段中,我们正在访问一个空队列。因此,take() 方法阻塞调用线程。
LinkedBlockingQueue 的阻塞特性与一些开销相关。这个代价是因为每个put或take操作在生产者线程或使用者线程之间都是锁争用的。因此,在许多生产者和消费者的情况下,put和take 动作可能会慢一些。
ConcurrentLinkedQueue
ConcurrentLinkedQueue 是一个无边界、线程安全且无阻塞的队列。
创建一个空的 ConcurrentLinkedQueue:
ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue();
同上面一样,我们也可以从现有集合创建 ConcurrentLinkedQueue:
不同于 LinkedBlockingQueue, ConcurrentLinkedQueue是非阻塞的队列。因此,即使队列为空(empty),它也不会阻塞线程。相反,它会返回 空(null) 。虽然它是无界的,但如果没有额外的内存来添加新元素,它依旧会抛出 java.lang.OutOfMemory 错误。 除了非阻塞之外,ConcurrentLinkedQueue还有其他特性。 在任何生产者-消费者场景中,消费者都不会满足于生产者;但是,多个生产者将相互竞争:
int element = 1;
ExecutorService executorService = Executors.newFixedThreadPool(2);
ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<>();
Runnable offerTask = () -> queue.offer(element);
Callable<Integer> pollTask = () -> {
while (queue.peek() != null) {
return queue.poll().intValue();
}
return null;
};
executorService.submit(offerTask);
Future<Integer> returnedElement = executorService.submit(pollTask);
assertThat(returnedElement.get().intValue(), is(equalTo(element)));
第一个任务 offerTask 向队列中添加元素,第二个任务 pollTask 从队列中检索元素。pollTask 首先检查队列中的元素,因为ConcurrentLinkedQueue是非阻塞的,并且可以返回null值。
两者异同
LinkedBlockingQueue 和 ConcurrentLinkedQueue 都是队列实现,并具有一些共同特征。让我们讨论一下这两个队列的相似之处:
- 都 实现 Queue 接口
- 它们都使用 linked nodes 存储节点
- 都适用于并发访问场景
区别:
总结
上述进行了queue队列之LinkedBlockingQueue 和 ConcurrentLinkedQueue的讲述及明确两则之间的区别,在项目中可以根据需要运用两者。
- 上一篇: 100个Java工具类之61:队列类Queue
- 下一篇: 7个技巧使你编写更好的 Java 单元测试
猜你喜欢
- 2024-09-08 Java阻塞队列中的异类,SynchronousQueue底层实现原理剖析
- 2024-09-08 100个Java工具类之61:队列类Queue
- 2024-09-08 阿里架构师浅析数据结构:队列在线程池等有限资源池中的应用
- 2024-09-08 【每日一学】Java数据结构探秘:队列与List的强大应用与性能优化
- 2024-09-08 使用Redis实现消息队列功能在Java中的应用
- 2024-09-08 『并发包入坑指北』之阻塞队列(阻塞队列poll方法)
- 2024-09-08 工作了这么久,你知道Java线程池容量应该设置多少么
- 2024-09-08 一文读懂,Java内置的延迟队列DelayQueue,原理及使用方法
- 2024-09-08 Java 消息队列的简单实现(java如何实现消息队列的监听)
- 2024-09-08 java 二叉树的层次遍历之队列的使用
你 发表评论:
欢迎- 最近发表
-
- Mozilla Firefox 139 Beta已上线 提供更快的HTTP/3上传速度
- Win8专享拷贝能暂停,Win7其实也可以
- ASP.NET利用WEBUPLOADER实现超大文件分片上传、断点续传
- 河汉大大的《断点续传》-------黑暗哨兵和向导的绝美爱恋
- 用C# 实现断点续传 (HTTP)
- 开源断点续传下载软件FDM获推6.21.0.5639版更新
- 前端大文件切片上传,断点续传、秒传等解决方案,VUE中使用实例
- SpringBoot 实战:文件上传之秒传、断点续传、分片上传
- 一文搞定SpringBoot分片上传、断点续传、大文件极速秒传功能
- SPRING-BOOT实现HTTP大文件断点续传分片下载
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)