最近学习了 BlockingQueue,发现 java 的 BlockingQueue 并不是每一个实现都按照 BlockingQueue 的语意来的,其中有不少坑。

直接上代码吧:

1、关于PriorityBlockingQueue,以下代码运行结果是什么(答案往下拉)?

BlockingQueue<Integer> queue = new PriorityBlockingQueue<>(2);
queue.put(9);
queue.put(1);
queue.put(8);
System.out.println("queue.size() = " + queue.size());
System.out.println("queue.take() = " + queue.take());
System.out.println("queue = " + queue);

2、关于 SynchronousQueue,以下代码运行结果是什么(答案往下拉)?

BlockingQueue<Integer> queue = new SynchronousQueue<>();
System.out.println("queue.offer(1) = " + queue.offer(1));
System.out.println("queue.offer(2) = " + queue.offer(2));
System.out.println("queue.offer(3) = " + queue.offer(3));
System.out.println("queue.size = " + queue.size());
System.out.println("queue.take() = " + queue.take());

3、总体测试,以下代码运行结果是什么(答案往下拉)?

offer(new ArrayBlockingQueue<>(2));
offer(new LinkedBlockingQueue<>(2));
offer(new PriorityBlockingQueue<>(2));
offer(new SynchronousQueue<>());
private static void offer(BlockingQueue<Integer> queue) throws Exception {
System.out.println("queue.getClass() = " + queue.getClass().getName());
System.out.println("queue.offer(1) = " + queue.offer(1));
System.out.println("queue.offer(2) = " + queue.offer(2));
System.out.println("queue.offer(3) = " + queue.offer(3));
System.out.println("queue.size() = " + queue.size());
System.out.println("queue.take() = " + queue.take());
}

下面公布答案:

1、关于PriorityBlockingQueue 运行结果:

原因:

(1).PriorityBlockingQueue put(Object) 方法不阻塞,内部直接调用 offer(Object) 方法
(2).PriorityBlockingQueue offer(Object) 方法不限制,初始化Queue大小是没用的
(3).PriorityBlockingQueue 插入对象会做排序,默认参照元素 Comparable 实现,或者显示地传递 Comparator(因为传入对象是Integer,是默认实现了Comparable的)

2、关于 SynchronousQueue 运行结果

原因:

(1).SynchronousQueue 是无空间,offer 永远返回 false
(2).SynchronousQueue take() 方法会被阻塞,必须被其他线程显示地调用 put(Object)

如果第1题、第2题你的回答都有问题,那么总结一下,再看第3题的答案吧

3、总体测试,运行结果

总体而言,BlockingQueue 最让人想不到的就是 PriorityBlockingQueue 和 SynchronousQueue 了。

总结一下:

(1)ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,FIFO(先进先出)。
(2)LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue,静态工厂方法 Executors.newFixedThreadPool() 使用了这个队列。
(3)SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法 Executors.newCachedThreadPool() 使用了这个队列。
(4)PriorityBlockingQueue:一个具有优先级的无限阻塞队列。

本文有参考小马哥的讲课。

记录 Java 的 BlockingQueue 中的一些坑的更多相关文章

  1. 需求:一个页面中需要用到多个字典数据。用于下拉选项,同时,需要将其保存为json格式。以便于key,value的相互转换。记录在实现过程中踩的坑

    本文涉及到的知识: Promise,all()的使用 js处理机制 reduce的用法 map的用法 同步异步 需求: 一个页面中需要用到多个字典数据.用于下拉选项,同时,需要将其保存为json格式. ...

  2. maven build和push image中遇到的坑(学习过程记录)

    最近在做jenkins的持续集成构建,其中一项是要实现docker容器化部署.项目本身是maven项目,我对于maven和docker都没有什么认知基础,于是求助百度和官网,从头开始啃起.遇到了不少的 ...

  3. java中的那些坑

    最近准备换工作,为了少让人家鄙视,就要狠狠地藐视这些面试题目.找了本电子书,发了有好多坑,都是特别简单,但是很少有人做对的题目.面对这样的题目,我却有一种兴奋的感觉,也许是因为一直做着重复的工作没有新 ...

  4. Java表达式中的那些坑

    [1]您确定真正了解后缀表达式与前缀表达式的区别吗? public class IncrementDemo{ public static void main(String[] args) { int ...

  5. Java面试中遇到的坑【填坑篇】

    看到大家对上篇<Java面试中遇到的坑>一文表现出强力的关注度,说明大家确实在面试中遇到了类似的难题.大家在文章留言处积极留言探讨面试中遇到的问题,其中几位同学还提出了自己的见解,我感到非 ...

  6. Java并发编程中线程池源码分析及使用

    当Java处理高并发的时候,线程数量特别的多的时候,而且每个线程都是执行很短的时间就结束了,频繁创建线程和销毁线程需要占用很多系统的资源和时间,会降低系统的工作效率. 参考http://www.cnb ...

  7. Netty中的那些坑

    Netty中的那些坑(上篇) 最近开发了一个纯异步的redis客户端,算是比较深入的使用了一把netty.在使用过程中一边优化,一边解决各种坑.儿这些坑大部分基本上是Netty4对Netty3的改进部 ...

  8. Java SE1.6中的Synchronized

    1 引言 在多线程并发编程中Synchronized一直是元老级角色,很多人都会称呼它为重量级锁,但是随着Java SE1.6对Synchronized进行了各种优化之后,有些情况下它并不那么重了,本 ...

  9. andriod8.1.0源码编译中的一个坑-package com.sun.javadoc does not exist

    这里记录编译过程中的一个坑!!! 编译过程中出现了下面的报错 external/doclava/src/com/google/doclava/ClassInfo.java:20: error: pac ...

随机推荐

  1. .NET多线程之线程安全,Lock(锁)、Monitor(同步访问)、LazyInitializer(延迟初始化)、Interlocked(原子操作)、static(静态)构造函数、volatile、

    1.什么是线程安全 线程安全是编程中的术语,指某个函数.函数库在多线程环境中被调用时,能够正确地处理多个线程之间的共享变量,使程序功能正确完成.一般来说,线程安全的函数应该为每个调用它的线程分配专门的 ...

  2. 艺赛旗RPA-处理无表头表格

    今天写一个demo,要求是对表格数据用价格为key进行排序 样本数据有两种格式: 一.第一行是一个大单元格 处理步骤: 在不变参数的情况下读取表格数据: 结果如下: 可以看见表头: Unnamed: ...

  3. 创建PaletteSet的一个问题

    下面是一个常规创建PaletteSet面板的代码: public static PaletteSet m_ps = null; [CommandMethod("MyPalette" ...

  4. 使用nginx+tomcat实现动静分离

    动态资源与静态资源的区别 微微的概括一下 静态资源: 当用户多次访问这个资源,资源的源代码永远不会改变的资源. 动态资源:当用户多次访问这个资源,资源的源代码可能会发送改变. 什么是动静分离 动静分离 ...

  5. 《VR入门系列教程》之2---VR头显

    什么是虚拟现实?     虚拟现实的目标:让人们相信真实地处于一个虚拟世界中.要达到这个目标就得让人们的大脑(负责视觉和运动感知部分)欺骗他们.不同技术合在一起才可以创造这种幻觉,包括:     全立 ...

  6. git rebase 理解

    摘录自:https://blog.csdn.net/wangnan9279/article/details/79287631

  7. java的System.currentTimeMillis()和System.nanoTime

    纳秒 ns(nanosecond):纳秒, 时间单位.一秒的10亿分之一,即等于10的负9次方秒.常用作 内存读写速度的单位,其前面数字越小则表示速度越快.   1纳秒=1000 皮秒   1纳秒 = ...

  8. Angular JS 中 指令详解

    Angular JS的强大功能就在于其可以自定义很多指令,现在就指令做一下详细的剖析. 一个Angular js 指令(directive)需要指定一个唯一的名字(myDirective)和一个函数, ...

  9. Linux平台 Oracle 19c RAC安装Part2:GI配置

    三.GI(Grid Infrastructure)安装 3.1 解压GI的安装包 3.2 安装配置Xmanager软件 3.3 共享存储LUN的赋权 3.4 使用Xmanager图形化界面配置GI 3 ...

  10. 七分钟理解什么是 KMP 算法

    本文是介绍 什么是 BF算法.KMP算法.BM算法 三部曲之一. KMP算法 内部涉及到的数学原理与知识太多,本文只会对 KMP算法 的运行过程. 部分匹配表 .next数组 进行介绍,如果理解了这三 ...