Java线程池队列类型介绍
Java线程池的核心实现类是ThreadPoolExecutor,其构造方法中的workQueue参数用于指定任务队列,所有队列都实现了BlockingQueue接口,常见的队列类型有以下几种:

1. ArrayBlockingQueue
基于数组实现的有界阻塞队列,创建时需要指定队列容量,队列满时再提交任务会根据线程池的拒绝策略处理。适合需要严格控制任务积压数量的场景,避免内存溢出。
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ArrayBlockingQueueDemo {
public static void main(String[] args) {
// 创建核心线程数为2,最大线程数为4,队列容量为10的线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2,
4,
60,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10)
);
// 提交15个任务,当队列满后才会创建非核心线程
for (int i = 0; i < 15; i++) {
int taskId = i;
executor.execute(() -> {
System.out.println("执行任务:" + taskId + ",线程名:" + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
executor.shutdown();
}
}
2. LinkedBlockingQueue
基于链表实现的阻塞队列,默认是无界的(容量为Integer.MAX_VALUE),也可以指定容量创建有界队列。无界队列下线程池的最大线程数参数会失效,因为队列永远不会满,不会创建非核心线程,适合任务量波动大但不需要限制积压的场景。
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class LinkedBlockingQueueDemo {
public static void main(String[] args) {
// 使用无界LinkedBlockingQueue,最大线程数参数不生效
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2,
4,
60,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>()
);
// 提交大量任务,只会创建2个核心线程,任务全部进入队列
for (int i = 0; i < 20; i++) {
int taskId = i;
executor.execute(() -> {
System.out.println("执行任务:" + taskId + ",线程名:" + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
executor.shutdown();
}
}
3. SynchronousQueue
同步移交队列,本身不存储元素,每个插入操作必须等待另一个线程的移除操作,否则插入线程会阻塞。使用该队列时,提交的任务会直接交给线程执行,如果没有空闲线程则会创建新线程,直到达到最大线程数,适合要求高吞吐、任务处理快的场景。
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class SynchronousQueueDemo {
public static void main(String[] args) {
// 使用SynchronousQueue,提交任务直接尝试交给线程执行
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2,
4,
60,
TimeUnit.SECONDS,
new SynchronousQueue<>()
);
// 提交5个任务,会创建2个核心线程+3个非核心线程执行
for (int i = 0; i < 5; i++) {
int taskId = i;
executor.execute(() -> {
System.out.println("执行任务:" + taskId + ",线程名:" + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
executor.shutdown();
}
}
4. PriorityBlockingQueue
支持优先级的无界阻塞队列,任务需要实现Comparable接口或者通过构造方法传入Comparator,队列会根据优先级排序,优先级高的任务会先被执行,适合需要按优先级处理任务的场景。
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
// 实现Comparable接口的任务类
class PriorityTask implements Runnable, Comparable<PriorityTask> {
private int priority;
private int taskId;
public PriorityTask(int priority, int taskId) {
this.priority = priority;
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("执行任务ID:" + taskId + ",优先级:" + priority + ",线程名:" + Thread.currentThread().getName());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public int compareTo(PriorityTask o) {
// 优先级数值越小,优先级越高
return Integer.compare(this.priority, o.priority);
}
}
public class PriorityBlockingQueueDemo {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2,
2,
60,
TimeUnit.SECONDS,
new PriorityBlockingQueue<>()
);
// 提交不同优先级的任务
executor.execute(new PriorityTask(3, 1));
executor.execute(new PriorityTask(1, 2));
executor.execute(new PriorityTask(2, 3));
executor.execute(new PriorityTask(0, 4));
executor.shutdown();
}
}
5. DelayedWorkQueue
这是ScheduledThreadPoolExecutor默认使用的队列,用于支持定时任务和周期性任务,队列中的任务会按照延迟时间排序,只有延迟时间到达的任务才会被取出执行。
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class DelayedWorkQueueDemo {
public static void main(String[] args) {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2);
// 提交一个延迟3秒执行的任务
executor.schedule(() -> {
System.out.println("延迟3秒执行的任务,线程名:" + Thread.currentThread().getName());
}, 3, TimeUnit.SECONDS);
// 提交一个初始延迟1秒,之后每隔2秒执行的周期性任务
executor.scheduleAtFixedRate(() -> {
System.out.println("周期性执行的任务,线程名:" + Thread.currentThread().getName());
}, 1, 2, TimeUnit.SECONDS);
}
}
Java线程池任务调度机制说明
线程池的任务调度流程遵循固定的规则,当调用execute()或者submit()方法提交任务时,会按以下步骤处理:
调度流程步骤
- 第一步:如果当前运行的线程数小于核心线程数,直接创建新的核心线程执行提交的任务,不管是否有核心线程空闲。
- 第二步:如果当前运行的线程数已经达到核心线程数,会将任务放入阻塞队列中等待。
- 第三步:如果队列已满,且当前运行的线程数小于最大线程数,会创建非核心线程执行任务。
- 第四步:如果当前运行的线程数已经达到最大线程数,且队列已满,会触发线程池的拒绝策略,处理无法执行的任务。
拒绝策略说明
当任务无法被线程池执行时,会触发以下四种内置拒绝策略:
| 拒绝策略类 | 策略说明 |
|---|---|
AbortPolicy | 默认策略,直接抛出RejectedExecutionException异常,中断任务提交流程 |
CallerRunsPolicy | 用提交任务的线程来执行任务,会降低任务提交速度,给线程池缓冲时间 |
DiscardPolicy | 直接丢弃任务,不做任何处理也不抛出异常 |
DiscardOldestPolicy | 丢弃队列中最旧的未执行任务,然后尝试重新提交当前任务 |
调度机制注意事项
非核心线程在空闲时间超过keepAliveTime后会被回收,而核心线程默认不会回收,除非设置了allowCoreThreadTimeOut为true。另外,使用无界队列时,因为队列永远不会满,所以永远不会触发非核心线程的创建,最大线程数参数会失效,实际运行线程数不会超过核心线程数。
在实际开发中,需要根据任务的类型选择合适的队列:CPU密集型任务适合使用较小的队列容量,避免任务积压导致响应变慢;IO密集型任务可以使用稍大的队列容量,充分利用线程资源。同时要避免使用无界队列处理不可控的任务量,防止内存溢出问题。
线程池BlockingQueue任务调度ThreadPoolExecutor修改时间:2026-07-06 11:21:16