BlockingQueue(阻塞队列)
Posted 暴躁的程序猿啊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BlockingQueue(阻塞队列)相关的知识,希望对你有一定的参考价值。
BlockingQueue
阻塞队列(BlockingQueue) 是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。
使用场景: 多线程并发处理,线程池!
队列 FIFO先进先出 一端写入一端取出
写入如果队列满了就必须阻塞等待 如果队列是空的必须阻塞等待生产
注意:BlockingQueue 不接受null值 试图添加一个null元素时会抛出异常
BlockingQueue 可以是限定容量的 超过给定容量时是无法添加的
JDK中七个队列
ArrayBolckingQueue(常用):基于数组的有界阻塞队列
LinkedBlockingQueue(常用):基于链表的有界阻塞队列 大小默认为 Integer最大值
PriorityBlockingQueue : 一个支持优先级排序的无界阻塞队列。
DelayQueue: 使用优先级队列实现的延迟无界阻塞队列
SynchronousQueue: 一个不存储元素的阻塞队列。
LinkedTransferQueue: 一个由链表结构组成的无界阻塞队列。
LinkedBlockingDeque: 一个由链表结构组成的双向阻塞队列
阻塞队列核心方法
方法类型 | 抛出异常 | 特殊值( 有返回值) | 阻塞 | 超时 |
---|---|---|---|---|
插入 | add | offer | put | offer |
移除 | remove | poll | take | poll |
判断队列首 | element | peek | - | - |
ArrayBolckingQueue使用示例:
演示各个API的使用
public class Test {
public static void main(String[] args) {
test1();
}
第一组会抛出异常API演示 add remove element
/**
* 抛出异常
*/
public static void test1(){
//指定队列大小
ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(3);
//add添加成功返回true
System.out.println(arrayBlockingQueue.add("1"));
System.out.println(arrayBlockingQueue.add("2"));
System.out.println(arrayBlockingQueue.add("3"));
//查看队首的元素是谁 1
System.out.println(arrayBlockingQueue.element());
//超过队列大小 add会抛出异常 Queue full
// System.out.println(arrayBlockingQueue.add("4"));
//remove取出一个元素 返回取出的值 如果队列为空 remove会抛出异常
// NoSuchElementException
System.out.println(arrayBlockingQueue.remove());
System.out.println(arrayBlockingQueue.remove());
System.out.println(arrayBlockingQueue.remove());
System.out.println(arrayBlockingQueue.remove());
}
第二组API使用
public static void test1(){
//队列的大小
ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(2);
//offer 添加一个元素 返回一个boolean值 成功返回true失败返回true
System.out.println(blockingQueue.offer(1));
System.out.println(blockingQueue.offer(2));
System.out.println(blockingQueue.offer(3));
System.out.println("----------------");
//检测队首元素
System.out.println(blockingQueue.peek());
//poll 取出一个元素 返回一个元素 队列为空时 取出null
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.peek());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
}
第三组阻塞API使用
放不进去了会一直阻塞直到有空位
/**
* 等待 一直阻塞
*/
public static void test1(){
ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(2);
try {
//put添加元素 没有返回值 满了一直阻塞
//队列大小为二 第三个元素放不进去 阻塞两秒过后就会结束
blockingQueue.put("1");
blockingQueue.put("2");
blockingQueue.put("3");
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
//取出元素 空了一直阻塞 返回值取出的元素
System.out.println(blockingQueue.take());;
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
第四组API使用
设置阻塞时间 超过阻塞时间没放进去就放弃等待
/**
* 等待 超时阻塞
*/
public static void test4(){
ArrayBlockingQueue<Object> blockingQueue = new ArrayBlockingQueue<>(2);
try {
//参数 插入的数值 超时时间 和 单位
blockingQueue.offer("1");
blockingQueue.offer("2");
blockingQueue.offer("3",2, TimeUnit.SECONDS);
System.out.println("------");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
以上是关于BlockingQueue(阻塞队列)的主要内容,如果未能解决你的问题,请参考以下文章
阻塞队列BlockingQueue一 SynchronousQueue
[Java并发编程实战] 阻塞队列 BlockingQueue(含代码,生产者-消费者模型)