线程池中常用的阻塞队列(BlockingQueue)是 java.util.concurrent
包中的一部分,用于在线程池中管理任务队列。阻塞队列对于线程池非常重要,因为它可以控制线程池中的任务队列的大小,并在队列为空或满时阻塞线程。下面是几种常用的阻塞队列实现:
1. ArrayBlockingQueue
-
特点:
- 基于数组结构的有界阻塞队列。
- 生产者和消费者共享同一个数组。
- 通过
put
和take
方法进行入队和出队操作。 - 支持公平和非公平两种模式。
-
适用场景:
- 适用于队列大小固定的场景。
- 需要控制最大任务数量以避免内存溢出。
2. LinkedBlockingQueue
-
特点:
- 基于链表结构的阻塞队列。
- 可以是无界的,也可以通过构造函数指定边界。
- 默认情况下是无界的,但实际上是有限的,因为 Java 虚拟机的堆空间是有限的。
- 通过
put
和take
方法进行入队和出队操作。
-
适用场景:
- 适用于不确定队列大小上限的场景。
- 需要一个相对较大的队列,但不希望指定确切的最大容量。
3. PriorityBlockingQueue
-
特点:
- 基于优先级堆的无界阻塞队列。
- 元素按自然顺序或由
Comparator
定义的顺序排列。 - 通过
put
和take
方法进行入队和出队操作。
-
适用场景:
- 适用于需要按照任务优先级进行调度的场景。
- 需要一个可以动态调整优先级的任务队列。
4. SynchronousQueue
-
特点:
- 特殊的无界队列,队列本身不能保存任何元素。
- 每次
put
必须等待一个take
或者offer
必须等待一个poll
。 - 实际上不是一个队列,而是一个传递元素的机制。
-
适用场景:
- 适用于希望立即执行任务且不希望任务排队等待的场景。
- 适用于线程池大小固定且希望将任务直接传递给工作线程的情况。
5. DelayQueue
-
特点:
- 一种特殊类型的无界阻塞队列。
- 队列中的元素是
Delayed
接口的实现。 - 元素在过期前一直阻塞,过期后才可被消费。
-
适用场景:
- 适用于需要延迟执行任务的场景。
- 例如定时任务或者缓存清理任务。
6. LinkedTransferQueue
-
特点:
- 基于链表的无界阻塞队列。
- 具有
transfer
方法,可以等待另一个线程接收一个元素。 - 通过
transfer
和take
方法进行入队和出队操作。
-
适用场景:
- 适用于生产者和消费者之间需要直接传递元素的场景。
- 适用于需要等待另一个线程接收数据的情况。
示例代码
下面是一个使用 ArrayBlockingQueue
的示例:
import java.util.concurrent.*;
public class BlockingQueueExample {
public static void main(String[] args) throws InterruptedException {
// 创建一个容量为 10 的 ArrayBlockingQueue
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
// 生产者线程
Thread producerThread = new Thread(() -> {
try {
for (int i = 0; i < 15; i++) {
queue.put("item" + i);
System.out.println("Produced item" + i);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("Producer was interrupted.");
}
});
// 消费者线程
Thread consumerThread = new Thread(() -> {
try {
for (int i = 0; i < 15; i++) {
String item = queue.take();
System.out.println("Consumed " + item);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("Consumer was interrupted.");
}
});
producerThread.start();
consumerThread.start();
producerThread.join();
consumerThread.join();
}
}
每种阻塞队列都有其特点和适用场景。例如,ArrayBlockingQueue
和 LinkedBlockingQueue
是最常见的选择,因为它们简单、易于使用。PriorityBlockingQueue
适用于需要优先级排序的任务。SynchronousQueue
适用于直接的线程间移交任务。DelayQueue
适用于需要延迟执行的任务。
选择哪种阻塞队列取决于具体的应用需求和性能考虑。