阻塞队列是Java并发包中提供的一种特殊队列,它在普通队列的基础上增加了两个附加操作:
阻塞插入:当队列满时,插入元素的线程会被阻塞,直到队列不满
阻塞移除:当队列空时,获取元素的线程会被阻塞,直到队列不空
public interface BlockingQueue<E> extends Queue<E> {
// 阻塞式插入
void put(E e) throws InterruptedException;
// 阻塞式获取
E take() throws InterruptedException;
}
阻塞队列主要用于:
线程协作的自然方式:阻塞队列提供了一种优雅的线程间通信机制,可以轻松的视线一些模式,如生产者-消费者模式:
// 生产者
public void run() {
while(true) {
queue.put(produceItem());
}
}
// 消费者
public void run() {
while(true) {
consume(queue.take());
}
}
解决生产消费速率不匹配问题:当生产速度 > 消费速度时,队列满会阻塞生产者;反之,当消费速度 > 生产速度时,队列空会阻塞消费者
避免显式线程同步:阻塞队列内置的线程安全机制避免了开发者手动实现wait/notify等复杂同步操作
其好处与坏处如下;
优点 | 说明 |
---|---|
简化开发 | 内置线程安全,避免手动同步 |
解耦生产消费 | 生产者和消费者互不依赖 |
流量控制 | 通过队列容量限制系统负载 |
平衡系统负载 | 平滑突发流量,削峰填谷 |
提高响应性 |
生产者不会被消费者拖慢 |
缺点 | 说明 |
---|---|
可能造成线程堆积 | 队列满时大量生产者线程阻塞 |
延迟问题 | 消息在队列中等待导致处理延迟 |
资源占用 | 队列积压会占用大量内存 |
死锁风险 | 不合理的容量设置可能导致系统僵死 |
调试困难 | 阻塞行为使问题难以复现 |