在 Java 中,线程池使用 java.util.concurrent
包中的 ThreadPoolExecutor
来管理线程。ThreadPoolExecutor
提供了几种不同类型的阻塞队列和拒绝策略,以便处理线程池中的任务调度和资源管理。
1. 阻塞队列(Blocking Queue)
阻塞队列用于保存等待执行的任务。ThreadPoolExecutor
支持以下几种阻塞队列:
- ArrayBlockingQueue:一个由数组支持的有界阻塞队列,按 FIFO(先进先出)原则对元素进行排序。
- LinkedBlockingQueue:一个由链表支持的可选有界阻塞队列。默认情况下,队列长度为 Integer.MAX_VALUE,但可以指定容量。
- SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等待另一个线程的相应移除操作。
- PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。队列中的元素根据其优先级自然顺序或者通过提供的 Comparator 进行排序。
2. 拒绝策略(Rejection Policy)
拒绝策略用于处理当线程池中的任务队列已满并且没有空闲线程时,提交的新任务。ThreadPoolExecutor
提供了以下几种内置的拒绝策略:
- AbortPolicy:默认拒绝策略。直接抛出
RejectedExecutionException
,阻止系统正常工作。 - CallerRunsPolicy:由调用线程执行该任务。不会真正丢弃任务,但是会影响系统的性能,因为它阻塞了任务提交的线程。
- DiscardPolicy:直接丢弃任务,不予任何处理或抛出异常。这种策略可能会导致任务丢失。
- DiscardOldestPolicy:丢弃最旧的未处理任务,然后重新尝试执行任务。这种策略可能导致任务无序执行。
示例代码:
public static void main(String[] args) {// 创建线程池ThreadPoolExecutor executor = new ThreadPoolExecutor(2,// 核心线程数为24,// 最大线程数为410, // 多余空闲线程的存活时间为10秒TimeUnit.SECONDS,// 存活时间的单位为秒new ArrayBlockingQueue<>(2),// 使用有界阻塞队列,容量为2Executors.defaultThreadFactory(),//默认的线程工厂new ThreadPoolExecutor.AbortPolicy() // 使用默认的拒绝策略(抛出 RejectedExecutionException));// 提交任务for (int i = 0; i < 10; i++) {int taskNumber = i;executor.execute(() -> {System.out.println("Executing task " + taskNumber);try {// 模拟任务执行时间Thread.sleep(2000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}});}// 关闭线程池executor.shutdown();}