不能直接用Executors.newFixedThreadPool实现优先级,因其内部使用无界LinkedBlockingQueue,不支持优先级排序;必须手动创建ThreadPoolExecutor并传入PriorityBlockingQueue及Comparator。
Executors.newFixedThreadPool 实现优先级因为 newFixedThreadPool 内部用的是无界 LinkedBlockingQueue,它不支持按任务优先级排序。哪怕你提交的是 PriorityTask,只要没重写队列的比较逻辑,所有任务就按 FIFO 入队出队,优先级形同虚设。
真正起作用的是线程池的 workQueue 参数——必须换成能排序的阻塞队列,比如 PriorityBlockingQueue,且要求任务实现 Comparable 或提供 Comparator。
核心是绕过 Executors 工厂方法,手动 new ThreadPoolExecutor,并传入支持排序的队列。注意三点:
corePoolSize 和 maximumPoolSize 设为相同值,才能保证“固定”数量(否则 PriorityBlockingQueue 的无界特性会让线程数动态伸缩)RejectedExecutionHandler,因为 PriorityBlockingQueue 无界但不等于“永不拒绝”——当线程数已达上限且队列满(极端情况),默认策略会抛 RejectedExecutionException
Comparable,或在 PriorityBlockingQueue 构造时传入 Comparator,否则排序行为未定义(可能随机)示例构造方式:
ThreadPoolExecutor executor = new ThreadPoolExecutor( 4, 4, 0L, TimeUnit.MILLISECONDS, new PriorityBlockingQueue<>(11, Comparator.comparingInt(t -> ((PriorityTask) t).priority)), new ThreadPoolExecutor.CallerRunsPolicy());
不能只加个 priority 字段就完事。PriorityBlockingQueue 在 offer/take 时调用 compareTo 或 compare,所以要么让任务实现 Comparable,要么靠外部 Comparator 显式提取优先级字段。
推荐用外部 Comparator 方式,更灵活、解耦:
Comparable)Comparator 中对 null 的处理,否则 PriorityBlockingQueue 可能抛 NullPointerException
简单任务封装示例:
public class PriorityTask implements Runnable { final int priority; final Runnable delegate; public PriorityTask(int priority, Runnable delegate) { this.priority = priority; this.delegate = delegate; } @Override public void run() { delegate.run(); }}
PriorityBlockingQueue 是无界的,但不是“无限安全”的:它内部用数组扩容,当任务持续高并发提交且消费慢时,会触发频繁扩容 + 数组拷贝,GC 压力陡增,甚至 OOM。
另一个关键限制:不保证同等优先级任务的执行顺序。也就是说,两个 priority=5 的任务,谁先被执行是不确定的——这跟 LinkedBlockingQueue 的严格 FIFO 不同。如果业务依赖“同优先级下先进先出”,得自己在 Comparator 中加入插入序号(如 AtomicLong 计数)作为第二排序键。
还有个容易被忽略的点:线程池的 prestartAllCoreThreads() 对优先级无效。预启动的线程只是空转等待,真正决定哪个任务先跑的,永远是队列头部元素,而不是哪个线程先抢到锁。