最近学习了 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. 「玩转Python」突破封锁继续爬取百万妹子图

    前言 从零学 Python 案例,自从提交第一个妹子图版本引来了不少小伙伴的兴趣.最近,很多小伙伴发来私信说,妹子图不能爬了!? 趁着周末试了一把,果然爬不动了,爬下来的都是些 0kb 的假图片,然后 ...

  2. Django工程的分层结构

    前言 传统上我们都知道在Django中的MTV模式,具体内容含义我们再来回顾一下: M:是Model的简称,它的目标就是通过定义模型来处理和数据库进行交互,有了这一层或者这种类型的对象,我们就可以通过 ...

  3. C# oleDb方法读取Excel文件

    今天学习的是从FTP上下载Excel文件,DataTable接收数据之后,在DataTable中通过筛选,删减修改之后把数据插入到DB相应表中. 优点:读取方式简单.读取速度快 缺点:除了读取过程不太 ...

  4. Netty-Pipeline深度解析

    首先我们知道,在NIO网络编程模型中,IO操作直接和channel相关,比如客户端的请求连接,或者向服务端发送数据, 服务端都要从客户端的channel获取这个数据 那么channelPipeline ...

  5. 异步编程之Async,Await和ConfigureAwait的关系

    在.NET Framework 4.5中,async / await关键字已添加到该版本中,简化多线程操作,以使异步编程更易于使用.为了最大化利用资源而不挂起UI,你应该尽可能地尝试使用异步编程.虽然 ...

  6. YOLO V1损失函数理解

    YOLO V1损失函数理解: 首先是理论部分,YOLO网络的实现这里就不赘述,这里主要解析YOLO损失函数这一部分. 损失函数分为三个部分: 代表cell中含有真实物体的中心. pr(object) ...

  7. [sublime3] 在linux下的终端中使用sublime3打开文件

    通过ln命令创建软连接实现 echo $PATH 查看路径 例 我的路径是: /home/rh/anaconda3/bin:/home/rh/bin:/home/rh/.local/bin:/usr/ ...

  8. 02、HTML 基础

    1.HTML 标题 HTML 标题(Heading)是通过<h1> - <h6> 标签来定义的. <!DOCTYPE html> <html> < ...

  9. C#中谁最快:结构还是类?

    前言 在内存当道的日子里,无论什么时候都要考虑这些代码是否会影响程序性能呢? 在现在的世界里,几乎不会去考虑用了几百毫秒,可是在特别的场景了,往往这几百毫米确影响了整个项目的快慢. 通过了解这两者之间 ...

  10. Python字典排序

    利用引出一个例子来理解 例如:比如使用Python字典排序,d={'a':1,'c':3,'b':2}按值升序排列,我们可以用sorted高阶函数或者用列表的.sort()方法.下面具体阐述两种排序方 ...