了解阻塞队列BlockingQueue
队列的特性:FIFO(先进先出)
其实就是写入和读取两个操作 写入和读取会有以下情况(不得不阻塞)
写入:如果队列满了,就必须阻塞等待(如果队列满了,就要阻塞等待,等其他队列出来了再进行写入操作)
读取:如果队列是空的,必须阻塞等待生产(读不到数据,需要先写入在进行读取)
阻塞队列:BlockingQueue 它其实是一个JUC下的接口并且和list,set同级,父类是collection,实现类有ArrayBlockingQueue(以数组实现的阻塞队列),LinkedBlockingQueue(以链表实现的阻塞队列),SynchronousQueue(同步队列)
它不是一个新的东西,和set,list同一级,都是collction下的接口,是一种更厉害的数据结构,它和Queue(队列,)是平级的,并且继承了Queue(队列,实现类有一个Deque(双端队列,也就是可以从左到右,从右到左执行,更加灵活多变),还有一个AbstractQueue(非阻塞队列),还有就是BlockingQueue(阻塞队列)),
使用场景:线程池和多线程并发处
队列家族关系图如下所示
以上就是一些概念,下面就开始写代码使用队列
其实和list,set一样主要就两个操作,添加 删除
但是根据不同的情况分为4组不同的API
- 抛出异常
- 不会抛出异常
- 阻塞等待
- 超时等待
方式 |
抛出异常 |
不会抛出异常,有返回值 |
阻塞等待(一直等待) |
超时等待(规定时间内等待) |
||||
添加 |
add |
offer |
put() |
offer(E e, long timeout, TimeUnit unit) |
||||
删除(移除) |
remove |
poll |
take() |
pollt(long timeout, TimeUnit unit) |
||||
检测队首(第一个进入队列的)元素 |
element |
peek |
阻塞不存在检测 |
阻塞不存在检测 |
创建阻塞队列
通过源码发现阻塞队列有一个重写方法,参数为队列初始大小(必须填写),是否公平(默认是不公平,可以不写,如果为true则为公平)
//创建BlockingQueue的实现类ArrayBlockingQueue(一个数组形的阻塞队列) //第一个参数不是泛型 而是队列的大小(可以存放多少个元素) //第二个参数表示是否公平,默认是不公平的,一般可以不用去指名 ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(5,false);
public ArrayBlockingQueue(int capacity) { this(capacity, false); } public ArrayBlockingQueue(int capacity, boolean fair) { if (capacity <= 0) throw new IllegalArgumentException(); this.items = new Object[capacity]; lock = new ReentrantLock(fair); notEmpty = lock.newCondition(); notFull = lock.newCondition(); }
1 第一组(抛出异常) add remove
如果操作不成功则会抛出异常
//创建BlockingQueue的实现类ArrayBlockingQueue(一个数组形的阻塞队列) //第一个参数不是泛型 而是队列的大小(可以存放多少个元素) //第二个参数表示是否公平,默认是不公平的,一般可以不用去指名 ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(5,false); //添加 参数为添加的元素 返回类型为布尔值 成功返回true 不成功返回false arrayBlockingQueue.add(1); //移除 arrayBlockingQueue.remove() //查看队首 arrayBlockingQueue.element()
添加:add()
关于add查看源码发现,需要一个Object类型的参数,返回一个boolan值(true或false),成功为true,失败为false
package com.wyh.BlockingQueue; import java.util.concurrent.ArrayBlockingQueue; /** * @program: JUC * @description: JUC下的阻塞队列demo * @author: 魏一鹤 * @createDate: 2022-02-20 19:45 **/ public class BlockingQueueDemo1 { public static void main(String[] args){ //创建BlockingQueue的实现类ArrayBlockingQueue(一个数组形的阻塞队列) //第一个参数不是泛型 而是队列的大小(可以存放多少个元素) //第二个参数表示是否公平,默认是不公平的,一般可以不用去指名 ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(5); //add添加方法 需要一个object型的参数 返回一个布尔值(成功为true,失败为false) //如果我们往队列里面添加元素的个数大于了创建队列的时候参数的大小,则会报错 //java.lang.IllegalStateException: Queue full) System.out.println(arrayBlockingQueue.add(1)); System.out.println(arrayBlockingQueue.add(2)); System.out.println(arrayBlockingQueue.add(3)); } }
true
true
true
注意:如果我们往队列里面添加元素的个数大于了创建队列的时候参数的大小,则会报错
package com.wyh.BlockingQueue; import java.util.concurrent.ArrayBlockingQueue; /** * @program: JUC * @description: JUC下的阻塞队列demo * @author: 魏一鹤 * @createDate: 2022-02-20 19:45 **/ public class BlockingQueueDemo1 { public static void main(String[] args){ //创建BlockingQueue的实现类ArrayBlockingQueue(一个数组形的阻塞队列) //第一个参数不是泛型 而是队列的大小(可以存放多少个元素) //第二个参数表示是否公平,默认是不公平的,一般可以不用去指名 ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(5); //add添加方法 需要一个object型的参数 返回一个布尔值(成功为true,失败为false) //如果我们往队列里面添加元素的个数大于了创建队列的时候参数的大小,则会报错 //java.lang.IllegalStateException: Queue full) System.out.println(arrayBlockingQueue.add(1)); System.out.println(arrayBlockingQueue.add(2)); System.out.println(arrayBlockingQueue.add(3)); System.out.println(arrayBlockingQueue.add(4)); System.out.println(arrayBlockingQueue.add(5)); System.out.println(arrayBlockingQueue.add(6)); } }
package com.wyh.BlockingQueue; import java.util.concurrent.ArrayBlockingQueue; /** * @program: JUC * @description: JUC下的阻塞队列demo四组API 第一组抛出异常 * @author: 魏一鹤 * @createDate: 2022-02-20 19:45 **/ //阻塞队列四组API:第一组抛出异常 public class BlockingQueueDemo1 { public static void main(String[] args){ test1(); } public static void test1(){ //创建BlockingQueue的实现类ArrayBlockingQueue(一个数组形的阻塞队列) //第一个参数不是泛型 而是队列的大小(可以存放多少个元素) //第二个参数表示是否公平,默认是不公平的,一般可以不用去指名 ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(3); //add添加方法 需要一个object型的参数 返回一个布尔值(成功为true,失败为false) //如果我们往队列里面添加元素的个数大于了创建队列的时候参数的大小,队列已经满了还要添加,则会报错 //java.lang.IllegalStateException: Queue full) 队列已满 System.out.println(arrayBlockingQueue.add(1)); System.out.println(arrayBlockingQueue.add(2)); System.out.println(arrayBlockingQueue.add(3)); //循环打印下标 使用 for i 循环 for (int i = 0; i < arrayBlockingQueue.size(); i++) System.out.println(i); //循环打印arrayBlockingQueue中的元素 使用foreach循环 for (Object o : arrayBlockingQueue) { System.out.println(o); } } }
true
true
true
0
1
2
1
2
3
删除:remove()
remove方法没有参数,返回类类型是一个E,E就是它弹出来的那个元素,它是一个往外弹的过程,遵循FIFO(先进先出),如果进入先后顺序是1,2,3那么出去先后顺序也是1,2,3
package com.wyh.BlockingQueue; import java.util.concurrent.ArrayBlockingQueue; /** * @program: JUC * @description: JUC下的阻塞队列demo四组API 第一组抛出异常 * @author: 魏一鹤 * @createDate: 2022-02-20 19:45 **/ public class BlockingQueueDemo1 { public static void main(String[] args){ test1(); } //第一组 抛出异常 public static void test1(){ //创建BlockingQueue的实现类ArrayBlockingQueue(一个数组形的阻塞队列) //第一个参数不是泛型 而是队列的大小(可以存放多少个元素) //第二个参数表示是否公平,默认是不公平的,一般可以不用去指名 ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<>(3); //add添加方法 需要一个object型的参数 返回一个布尔值(成功为true,失败为false) //如果队列已经满了还要添加,则会报错 //java.lang.IllegalStateException: Queue full) 队列已满 抛出异常 System.out.println(arrayBlockingQueue.add(1)); System.out.println(arrayBlockingQueue.add(2)); System.out.println(arrayBlockingQueue.add(3)); //分隔符 方便观看 System.out.println("-------------------------------"); //根据FIFO先进先出规格 弹出先进去的三个元素 System.out.println(arrayBlockingQueue.remove()); System.out.println(arrayBlockingQueue.remove()); System.out.println(arrayBlockingQueue.remove()); } }