Java高频面试题:什么是阻塞队列?
1.什么是阻塞线程?

阻塞队列和普通的队列的区别是:
当阻塞队列是空的,从队列中获取元素的操作将会被阻塞;
当阻塞队列是满的,往队列里添加元素的操作将会被阻塞;
试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素;
同样,试图从满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他线程从列中移除一个或者多个元素或者完全清空队列使队列重新变得空闲起来并后续新增。
在多线程领域里:所谓阻塞,在某些情况下会挂起线程,一旦条件满足,被挂起的线程又会自动被唤醒。
2.为什么需要BlockingQueue?
好处是我们不需要关心什么时候需要阻塞线程,什么时候需要唤起线程,因为这一切BlockingQueue都给你一手包办了。
在concurrent包发布以前,在多线程环境下,我们每个程序员必须去自己控制这些细节,尤其还要兼顾效率和线程安全,而这会给我们的程序带来不小的复杂度。
3.有哪些常见的阻塞队列?(加粗的是常用的)
- ArrayBlockingQueue:由数组结构组成的有界阻塞队列
- LinkedBlockingQueue:由链表结构组成的有界(但大小默认值为Integer.MAX_VALUE)阻塞队列
- PriorityBlockingQueue:支持优先级排序的无界阻塞队列
- DelayBlockingQueue:使用优先级队列实现的延迟无界阻塞队列
- SynchronousQueue:不存储元素的阻塞队列,也即单个元素的队列,只存一个元素
- LinkedTransferQueue:由链表结构组成的无界阻塞队列
- LinkedBlockingDeque:由链表结构组成的双向阻塞队列
SynchronousQueue没有容量。与其他BlockingQueue不同,SynchronousQueue是不存储元素,每一个put操作必须要等待一个take操作,否则不能继续添加元素,反之亦然。
4.BlockingQueue的核心方法

BlockingQueue的核心方法:
插入 add(e) offer(e) put(e) offer(e,time,unit)
移除 remove() poll() take() poll(time,unit)
检查 element() peek()
- 当阻塞队列满的时候,再往队列里add插入元素会抛出IllegalStateException: Queue full异常;
- 当阻塞队列空的时候,再往队列里remove移除元素,会抛出NoSuchElementException异常;
- 使用offer(e)添加元素,不抛异常,成功返回true,失败返回false;
- 使用poll()移除元素时,不抛异常,成功返回队列里的元素值,失败返回null;
- 当阻塞队列满的时候,生产者线程继续使用put(e)插入元素,会一直阻塞直到put成功,或者响应中断退出;
- 当阻塞队列空的时候,消费者线程试图从队列里take元素,队列会一直阻塞,直到消费者线程可用;
- 当阻塞队列满时,会等待一段时间,超时后退出:offer(e,time,unit)和poll(time,unit)。
演示示例:
(1)ArrayBlockingQueue添加元素示例:创建了一个大小为3的阻塞队列,当存入第四个元素的时候,抛出IllegalStateException: Queue full异常。
public class BlockingQueueDemo { public static void main(String[] args) { BlockingQueue blockingQueue = new ArrayBlockingQueue(3); System.out.println(blockingQueue.add('a')); System.out.println(blockingQueue.add('b')); System.out.println(blockingQueue.add('c')); System.out.println(blockingQueue.add('d')); } }报错:Exception in thread "main" java.lang.IllegalStateException: Queue full

(2)ArrayBlockingQueue移除元素示例:当阻塞队列为空时,移出元素抛出NoSuchElementException异常
public class BlockingQueueDemo { public static void main(String[] args) { BlockingQueue blockingQueue = new ArrayBlockingQueue(3); System.out.println(blockingQueue.add('a')); System.out.println(blockingQueue.add('b')); System.out.println(blockingQueue.add('c')); // System.out.println(blockingQueue.add('d')); System.out.println(blockingQueue.remove()); System.out.println(blockingQueue.remove()); System.out.println(blockingQueue.remove()); System.out.println(blockingQueue.remove()); } }
报错:NoSuchElementException

多