Java进阶:BlockingQueue阻塞队列的使用

it2024-01-08  62

文章目录

1. 概述2. 常用的阻塞队列3. 操作方法3.1 抛出异常3.2 特殊值3.3 阻塞3.4 超时

1. 概述

相比平时讨论的队列,阻塞队列增加了阻塞的功能:

当有限长度的队列填满了数据时,继续往队列添加数据的线程将被阻塞住,持续等待,直到超时或队列数据被消费而腾出空间当队列数据为空时,消费线程会因为取不到数据而被阻塞,直到生产线程往队列添加数据,此时成功取到数据而不再阻塞

2. 常用的阻塞队列

ArrayBlockingQueue:由数组结构组成的有界阻塞队列,底层的出入队由同一个ReentrantLock加锁控制,可以传递fair参数指定使用公平锁 or 非公平锁LinkedBlockingQueue:由链表结构组成的有界阻塞队列(容量默认是Integer.MAX_VALUE,因此也可以理解成无界)。其出入队由不同的ReentrantLock控制,因此性能优于ArrayBlockingQueueSynchronousQueue:只存储一个元素的阻塞队列,容量大小只有1

3. 操作方法

方法类型抛出异常特殊值阻塞超时添加add(e)offer(e)put()offer(e,time,unit)移除remove()poll()take()poll(time,unit)获取element()peek()——

3.1 抛出异常

以下情况将直接抛出异常:

队列满了,调用 add()队列为空,调用 remove()队列为空,调用 element() BlockingQueue<String> queue = new ArrayBlockingQueue<>(3); queue.add("a"); queue.add("b"); queue.add("c"); //抛出异常 queue.add("d");

3.2 特殊值

队列满了,调用 offer(),将返回false,否则返回true队列为空,调用 poll(),将返回false,否则返回true队列为空,调用 peek(),将返回null,否则返回队列元素 BlockingQueue<String> queue = new ArrayBlockingQueue<>(3); //输出true System.out.println(queue.offer("a")); System.out.println(queue.offer("b")); System.out.println(queue.offer("c")); //输出false System.out.println(queue.offer("d"));

3.3 阻塞

队列满了,调用 put(),线程将被阻塞队列为空,调用take(),线程将被阻塞 BlockingQueue<String> queue = new ArrayBlockingQueue<>(3); new Thread(() -> { //往容量为3的堵塞队列添加4个元素,到第4个将被阻塞 for (int i = 1; i <= 4; i++){ String elem = "a" + i; try { queue.put(elem); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "添加元素:" + elem); } }, "Thread-1").start(); Thread.sleep(3000); //等待3秒,保证上面的线程执行完毕 new Thread(() -> { System.out.println(Thread.currentThread().getName() + "移除了一个元素"); try { //移除1个元素,这时候线程1将恢复执行 queue.take(); } catch (InterruptedException e) { e.printStackTrace(); } }, "Thread-2").start();

输出如下:

Thread-1添加元素:a1 Thread-1添加元素:a2 Thread-1添加元素:a3 Thread-2移除了一个元素 Thread-1添加元素:a4

3.4 超时

超时方法是 3.2特殊值 的升级版,只是参数加了个超时时间。执行失败的时候不会直接返回false,而是会等待一段时间,如果在时间到期前操作成功会返回true,否则才返回false。

BlockingQueue<String> queue = new ArrayBlockingQueue<>(3); for (int i = 1; i <= 4; i++){ String elem = "a" + i; boolean result = queue.offer(elem, 5, TimeUnit.SECONDS); System.out.println(new Date() + "---->" + Thread.currentThread().getName() + "添加数据:" + elem + ",结果:" + result); }

输出如下,最后一个false间隔了5秒才返回

Wed Oct 21 14:28:33 CST 2020---->main添加数据:a1,结果:true Wed Oct 21 14:28:33 CST 2020---->main添加数据:a2,结果:true Wed Oct 21 14:28:33 CST 2020---->main添加数据:a3,结果:true Wed Oct 21 14:28:38 CST 2020---->main添加数据:a4,结果:false
最新回复(0)