Java中的阻塞队列简介

生产者消费者模型相信大家都知道,我们使用普通的任务队列时要手动防止并发,代码比较繁琐,JDK给我们提供了线程安全的阻塞队列BlockingQueue来简化我们的代码。

总览

BlockingQueue是一个接口,他定义了阻塞队列中的总体行为,我们来看一下他的主要方法

他给我们提供了多种取出与存放操作,根据上面的图片就可以清楚的了解各种方法不同行为。阻塞队列并不允许存放null元素,阻塞队列分为有界和无界队列,有界即需要指定队列容量,无界则队列容量上限为Integer.MAX_VALUE。

JDK一共提供了7种BlockingQueue的实现类(其实在ScheduledThreadPoolExecutor中还有一个内部类,这里不讨论),我们分别简单介绍下。

1.ArrayBlockingQueue

由数组实现的有界阻塞队列,使用时必须指定容量大小。这里写顺便分析下他如何支持多线程的。先来看下他的几个实例域

主要通过上面的俩个条件Condition来实现生产者与消费者的协调,condition用来与lock共同实现线程的等待通知机制(也可以用原来的synchronized与object的wait和notify来实现)。接下来看入队的方法

这里以阻塞的put方法为例,首先获取锁,判断数组中元素是否已经满了,满了的话调用notFull的await方法,直到有消费者消费掉元素后调用notFull的signal方法后队列有剩余空间才能继续入队。数组有空闲容量的情况下调用enqueue方法,将元素放入数组后,调用notEmpty的signal方法,告诉消费者队列中已经有元素了,可以来消费了。

再来看与之对应的阻塞的take方法

逻辑基本就是和put方法相反的,数组为空时,await等待,直到队列有元素时notEmpty.notify通知进行消费,消费之后通知生产者队列有空余位置。

2.DelayQueue

无界延时队列,他可以在指定时间后取出任务。

可以看到,该队列中的元素必须继承Delayed接口,而Delayed又继承了Comparable接口,所以元素就必须实现Delayed中的getDelay方法用于获取延时时间,与Comparable中的compareTo方法用于比较时间。

put的时候其实是调用了PriorityQueue的offer方法,PriorityQueue为优先级队列,底层由堆实现(对堆不太了解的小伙伴建议阅读红色算法书第四版,比那本经典的算法要简单一些而且书中的数据结构都是使用java实现的),DelayQueue将最先执行的任务放在队头。

取出方法如图,首先取出队头元素判断delay时间是否小于等于0,若是则代表立即执行,若不是调用condition的awaitNanos等待相应时间后再执行。这里getDelay方法的实现是比较重要的

网图

基本上是按照这样的模式来实现自己的延时任务类。

3.LinkedBlockingDeque

基于链表实现的可选择界限的双端阻塞队列,可选择界限意味着可以在构造函数中指定容量,也可以不指定,不指定意味着容量为Integer.MAX_VALUE.

4.LinkedBlockingQueue

基于链表实现的可选择界限的阻塞队列

5.LinkedTransferQueue

引用自http://ifeve.com/java-blocking-queue/:基于链表实现的无界Transfer队列。TransferQueue是一个生产者有可能等待消费者去接收的阻塞队列,它主要有俩个方法,transfer:如果当前有消费者正在等待接收元素(消费者使用take()方法或带时间限制的poll()方法时),transfer方法可以把生产者传入的元素立刻transfer给消费者。如果没有消费者在等待接收元素,transfer方法会将元素存放在队列的tail节点,并等到该元素被消费者消费了才返回;tryTransfer:用来试探生产者传入的元素是否能直接传给消费者。如果没有消费者等待接收元素,则返回false。和transfer方法的区别是tryTransfer方法无论消费者是否接收,方法立即返回。而transfer方法是必须等到消费者消费了才返回。对于带有时间限制的tryTransfer(E e, long timeout, TimeUnit unit)方法,则是试图把生产者传入的元素直接传给消费者,但是如果没有消费者消费该元素则等待指定的时间再返回,如果超时还没消费元素,则返回false,如果在超时时间内消费了元素,则返回true。

6.PriorityBlockingQueue

基于堆实现的优先级阻塞队列,默认按元素的自然顺序排序。

7.SynchronousQueue

每个插入操作必须等待另一个线程的相应移除操作的队列,该队列是不能存储元素的,可以看成是一个传送带。降低了将数据从生产者移动到消费者的延迟。

最后:我写着写着就总感觉和以前看过的一篇文章好像雷同了(尴尬),找了好久终于找到那篇博文了http://ifeve.com/java-blocking-queue/,果然是受了这篇文章的影响,这篇文章作者是蚂蚁金服技术专家方腾飞。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358

推荐阅读更多精彩内容

  • 本文是我自己在秋招复习时的读书笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那...
    波波波先森阅读 11,273评论 4 56
  • 本文摘自《Java并发编程的艺术-方腾飞》 本节将介绍什么是阻塞队列,以及Java中阻塞队列的4种四种处理方式,并...
    Briarbear阅读 427评论 0 1
  • 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线...
    端木轩阅读 1,005评论 0 2
  • 所谓的当代新青年,喜欢把谢谢挂在嘴边,乍一听觉得你有家教懂礼貌,第二次听好孩子真客套,经常听到麻蛋好烦,听腻了闭嘴...
    LeonCan梁大可阅读 166评论 0 0
  • 第一次听到《地心》 北京爱情故事, 高三暑假 “你充满了我的全部思绪 像紫罗兰香般挥之不去” “你充满了我的辽阔心...
    Alice王志荣阅读 417评论 0 0