Java如何实现支持特殊任务优先调度的自定义ThreadPoolExecutor
自定义线程池实现方案
JDK 本身没有内置符合该需求的线程池实现,需要基于ThreadPoolExecutor做自定义扩展,具体实现逻辑如下:
实现步骤
1. 定义特殊任务标记接口
用来区分普通任务和需要调整调度逻辑的特殊任务:
public interface PriorityTask extends Runnable { // 仅做标记用,无需实现额外方法 }
2. 自定义线程池重写execute逻辑
核心调整特殊任务的调度逻辑:核心线程占满后优先创建非核心线程,达到最大线程数后插入队列头部优先执行:
import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class CustomScheduledThreadPool extends ThreadPoolExecutor { public CustomScheduledThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, ThreadFactory threadFactory) { // 用支持双端操作的LinkedBlockingDeque作为队列,支持队首插入 super(corePoolSize, maximumPoolSize, keepAliveTime, unit, new LinkedBlockingDeque<>(), threadFactory); } @Override public void execute(Runnable command) { // 普通任务走ThreadPoolExecutor原生默认逻辑 if (!(command instanceof PriorityTask)) { super.execute(command); return; } int currentPoolSize = getPoolSize(); // 核心线程未满,走原生逻辑创建核心线程执行 if (currentPoolSize < getCorePoolSize()) { super.execute(command); return; } // 核心线程已满、未达最大线程数,直接尝试创建非核心线程执行 if (currentPoolSize < getMaximumPoolSize()) { // 第二个参数false代表创建非核心线程 if (addWorker(command, false)) { return; } } // 已达最大线程数,将特殊任务插入队列最前端优先调度 ((LinkedBlockingDeque<Runnable>) getQueue()).offerFirst(command); } }
注意事项
- 必须使用
LinkedBlockingDeque作为队列实现,才能支持offerFirst方法将任务插入队首,如果替换为其他阻塞队列会触发类型转换异常。 - 多个特殊任务同时插入队列时,后插入的任务会排在最前面,优先级最高。
- 特殊任务的优先级仅体现在队列调度顺序上,不会中断正在执行的普通任务,只会比队列中已有的普通任务更早被空闲线程拉取执行。
内容的提问来源于stack exchange,提问作者mr.Nobody
相关产品推荐
相关产品推荐

