JAVA中的阻塞队列
来源:互联网 发布:ios更新系统 数据丢失 编辑:程序博客网 时间:2024/04/20 09:02
一.什么是阻塞队列?
阻塞队列是一个在队列基础上又支持了两个附加操作的队列。
2个附加操作:
- 支持阻塞的插入方法:队列满时,队列会阻塞插入元素的线程,直到队列不满。
- 支持阻塞的移除方法:队列空时,获取元素的线程会等待队列变为非空。
二.阻塞队列的应用场景
阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里取元素的线程。简而言之,阻塞队列是生产者用来存放元素、消费者获取元素的容器。
三.几个方法
在阻塞队列不可用的时候,上述2个附加操作提供了4种处理方式(以下来自JDK1.8文档):
从上表我们可以看出,当队列满时,如果我们插入元素,那么会有抛异常、返回特定值、阻塞和超时退出4种情况。相对于取元素(队列空)也有这4种情况。
四.JAVA里的阻塞队列
JAVA 7 提供了7个阻塞队列,如下
①:ArrayBlockingQueue 数组结构组成的有界阻塞队列。
此队列按照先进先出(FIFO)的原则对元素进行排序,但是默认情况下不保证线程公平的访问队列,即如果队列满了,那么被阻塞在外面的线程对队列访问的顺序是不能保证线程公平(即先阻塞,先插入)的。
②:LinkedBlockingQueue一个由链表结构组成的有界阻塞队列
此队列按照先出先进的原则对元素进行排序
③:PriorityBlockingQueue支持优先级的无界阻塞队列
④:DelayQueue支持延时获取元素的无界阻塞队列,即可以指定多久才能从队列中获取当前元素
⑤:SynchronousQueue不存储元素的阻塞队列,每一个put必须等待一个take操作,否则不能继续添加元素。并且他支持公平访问队列。
⑥:LinkedTransferQueue由链表结构组成的无界阻塞TransferQueue队列。相对于其他阻塞队列,多了tryTransfer和transfer方法
- transfer方法,如果当前有消费者正在等待接收元素(take或者待时间限制的poll方法),transfer可以把生产者传入的元素立刻传给消费者。如果没有消费者等待接收元素,则将元素放在队列的tail节点,并等到该元素被消费者消费了才返回。
- tryTransfer方法,用来试探生产者传入的元素能否直接传给消费者。,如果没有消费者在等待,则返回false。和上述方法的区别是该方法无论消费者是否接收,方法立即返回。而transfer方法是必须等到消费者消费了才返回。
⑦:LinkedBlockingDeque链表结构的双向阻塞队列,优势在于多线程入队时,减少一半的竞争。
五.阻塞队列的实现原理##**
通知模式实现:所谓通知模式,就是当生产者往满的队列里添加元素时会阻塞住生产者,当消费者消费了一个队列中的元素后,会通知生产者当前队列可用。例如ArrayBlockingQueue使用了Condition来实现。
最后我们写一个利用阻塞队列的实现原理来实现通知的Demo:
package Graphics;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.BlockingQueue;/** * * @author vayne 子线程执行3次,主线程执行5次,然后如此循环20次; */public class BlockingQueueDemo{ final static Business buse = new Business(); public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub for (int i = 0; i < 20; i++) { buse.sub(i); } } }).start(); for (int i = 0; i < 20; i++) { buse.main(i); } System.out.println("*************************"); }}// 业务逻辑类class Business{ ArrayBlockingQueue<Integer> queue1 = new ArrayBlockingQueue<>(1); ArrayBlockingQueue<Integer> queue2 = new ArrayBlockingQueue<>(1); // 2个阻塞队列,首先向2中放入一个元素, // 先是sub线程放的时候阻塞,然后main往1中放一个并继续执行,执行完毕取出2里面的元素让sub得以执行, // 2再取出1中的元素让main得以执行,如此往复 { try { queue2.put(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void sub(int i) { try { queue2.put(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } for (int j = 0; j < 3; j++) { System.out.println("sub sub sub" + j + ", loop" + i); } try { queue1.take(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void main(int i) { try { queue1.put(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } for (int j = 0; j < 5; j++) { System.out.println("main" + j + ", loop " + i); } try { queue2.take(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}
运行结果如下:
main0, loop 0main1, loop 0main2, loop 0main3, loop 0main4, loop 0sub sub sub0, loop0sub sub sub1, loop0sub sub sub2, loop0main0, loop 1main1, loop 1main2, loop 1main3, loop 1main4, loop 1sub sub sub0, loop1sub sub sub1, loop1sub sub sub2, loop1main0, loop 2main1, loop 2main2, loop 2main3, loop 2main4, loop 2sub sub sub0, loop2sub sub sub1, loop2sub sub sub2, loop2main0, loop 3main1, loop 3main2, loop 3main3, loop 3main4, loop 3sub sub sub0, loop3sub sub sub1, loop3sub sub sub2, loop3main0, loop 4main1, loop 4main2, loop 4main3, loop 4main4, loop 4sub sub sub0, loop4sub sub sub1, loop4sub sub sub2, loop4main0, loop 5main1, loop 5main2, loop 5main3, loop 5main4, loop 5sub sub sub0, loop5sub sub sub1, loop5sub sub sub2, loop5main0, loop 6main1, loop 6main2, loop 6main3, loop 6main4, loop 6sub sub sub0, loop6sub sub sub1, loop6sub sub sub2, loop6main0, loop 7main1, loop 7main2, loop 7main3, loop 7main4, loop 7sub sub sub0, loop7sub sub sub1, loop7sub sub sub2, loop7main0, loop 8main1, loop 8main2, loop 8main3, loop 8main4, loop 8sub sub sub0, loop8sub sub sub1, loop8sub sub sub2, loop8main0, loop 9main1, loop 9main2, loop 9main3, loop 9main4, loop 9sub sub sub0, loop9sub sub sub1, loop9sub sub sub2, loop9main0, loop 10main1, loop 10main2, loop 10main3, loop 10main4, loop 10sub sub sub0, loop10sub sub sub1, loop10sub sub sub2, loop10main0, loop 11main1, loop 11main2, loop 11main3, loop 11main4, loop 11sub sub sub0, loop11sub sub sub1, loop11sub sub sub2, loop11main0, loop 12main1, loop 12main2, loop 12main3, loop 12main4, loop 12sub sub sub0, loop12sub sub sub1, loop12sub sub sub2, loop12main0, loop 13main1, loop 13main2, loop 13main3, loop 13main4, loop 13sub sub sub0, loop13sub sub sub1, loop13sub sub sub2, loop13main0, loop 14main1, loop 14main2, loop 14main3, loop 14main4, loop 14sub sub sub0, loop14sub sub sub1, loop14sub sub sub2, loop14main0, loop 15main1, loop 15main2, loop 15main3, loop 15main4, loop 15sub sub sub0, loop15sub sub sub1, loop15sub sub sub2, loop15main0, loop 16main1, loop 16main2, loop 16main3, loop 16main4, loop 16sub sub sub0, loop16sub sub sub1, loop16sub sub sub2, loop16main0, loop 17main1, loop 17main2, loop 17main3, loop 17main4, loop 17sub sub sub0, loop17sub sub sub1, loop17sub sub sub2, loop17main0, loop 18main1, loop 18main2, loop 18main3, loop 18main4, loop 18sub sub sub0, loop18sub sub sub1, loop18sub sub sub2, loop18main0, loop 19main1, loop 19main2, loop 19main3, loop 19main4, loop 19sub sub sub0, loop19*************************sub sub sub1, loop19sub sub sub2, loop19
本文的Demo可以在我的github中找到。
- Java中的阻塞队列
- Java中的阻塞队列
- Java中的阻塞队列
- java中的阻塞队列
- JAVA中的阻塞队列
- Java中的阻塞队列
- Java中的阻塞队列
- Java中的阻塞队列
- Java中的阻塞队列
- Java中的阻塞队列
- Java中的阻塞队列
- java中的阻塞队列
- Java中的阻塞队列
- Java中的阻塞队列
- Java中的阻塞队列
- Java中的阻塞队列
- Java中的阻塞队列
- Java中的阻塞队列
- 关于Xcode编译性能优化的研究工作总结
- Ultra-Pull-To-Refresh动态添加View不能正常显示BUG解决方法
- js时间段列表生成方法
- Android自定义捕获Application全局异常
- hdu 1281 棋盘游戏 二分图匹配 匈牙利算法 暴力
- JAVA中的阻塞队列
- HelloWorld Driver
- 欢迎使用CSDN-markdown编辑器
- Apache OFBiz 学习笔记 之 服务引擎 二
- javascript中的||操作符与&&操作符
- 彻底解决数据库去中心化问题
- “睡城”通州的逆袭:房价大涨40% 限制人口落户
- String详解(一):如何理解String
- php 将中文字符串转成汉语拼音