【Java并发编程】阻塞队列 BlockingQueue

见贤思齐焉,见不贤而内自省也。—《论语》

Java5.0 增加了两种新的容器类型,它们是指:Queue 和 BlockingQueue。Queue 用来临时保存一组等待处理的元素。BlockingQueue 扩张了 Queue 接口,增加了可阻塞的插入和获取等操作。

BlockingQueue 通常运用于一个线程生产对象放入队列,另一个线程从队列获取对象并消费,这是典型的生产者消费者模型。

生产者线程持续生产新对象并插入队列,如果队列已满,那么插入对象的操作会一直阻塞,直到队列中出现可用的空间。消费者线程持续从队列获取对象,如果队列为空,那么获取操作会一直阻塞,直到队列中出现可用的新对象。BlockingQueue 简化了生产者-消费者设计的实现过程,它支持任意数量的生产者和消费者。

BlockingQueue 的核心方法:

offer(E): 向队列插入元素,并返回插入成功与否。本方法不阻塞当前执行线程。

put(E) : 向队列插入元素,如果队列已满,则会阻塞当前线程直至元素加入队列。

take() : 获取队列的首位元素,如果队列为空,则阻塞当前线程直至队列有元素并取走。

poll():获取队列首个元素,指定时间内一旦数据可取,则立即返回;否则返回失败。

remove(E):删除队列中的元素,返回成功与否。

BlockingQueue 的实现

BlockingQueue是一个接口,所以你必须使用它的实现来使用它。它的实现包括以下几个:

ArrayBlockingQueue:基于数组实现的有界队列(FIFO),使用一把全局锁并行对 queue 读写操作,同时使用两个 Condition 阻塞队列为空时的取操作和队列为满时的写操作。

LinkedBlockingQueue:基于已链接节点的,范围上限为 Integer.MAX_VALUE 的 blocking queue(FIFO)。主要操作 put 和 take 都是阻塞的。

DelayQueue:当指定的延迟时间到了,才能够从队列中获取元素。它没有大小限制,因此插入元素时不会阻塞,而只有获取元素时才会被阻塞。它的用法可以参考下面两篇博客:http://www.cnblogs.com/jobs/archive/2007/04/27/730255.html,http://www.cnblogs.com/sunzhenchao/p/3515085.html

PriorityBlockingQueue: 基于优先级的阻塞队列,但需要注意的是PriorityBlockingQueue并不会阻塞数据生产者,而只会在没有可消费的数据时,阻塞数据的消费者。

SynchronoutQueue:它的内部同时只能够容纳单个元素。如果该队列已有一个元素的话,试图向队列插入一个新元素线程会阻塞,知道另一个线程将该元素从队列中拿走。同样,如果该队列为空,试图向队列中抽取一个元素的线程将会阻塞,知道另一个线程向队列中插入一个新的元素。SynchronousQueue适合一对一的匹配场景,没有容量,无法缓存。它的用法强烈推荐博客: http://www.cnblogs.com/leesf456/p/5560362.html

BlockingQueue的使用

这是一个使用 BlockingQueue 的例子,本例使用 ArrayBlockingQueue 实现。首先,BlockingQueueTest 创建一个生产者线程 Procucer, 把字符存放进共享队列。然后创建三个消费者线程 Consumer,把字符串从队列中取出。Consumer 取到最后一个字符串时,中断所有消费者线程,结束程序。

执行结果:

总结

本文完毕,如对你有帮助,请关注我,谢谢~

参考

https://blog.csdn.net/defonds/article/details/44021605/

http://www.cnblogs.com/leesf456/p/5428630.html

《并发编程实战》

本文原创首发于微信公众号 [ 林里少年 ],欢迎关注第一时间获取更新。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180530G20GUL00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券