写在前面
设想一下,在我们的项目中存在一个边缘的业务流程,它并不频繁地被触发。在设计线程池时,我回想起了线程池的常见配置原则。为了最大限度地节省资源,我将核心线程数(corePoolSize)设置为0。这样的配置是否能够顺利执行任务呢?
线程池配置原则回顾
在任务提交时,线程池会根据以下策略进行处理:
- 如果线程池中的线程数少于核心线程数,则创建一个新线程来执行任务。
- 如果线程池中的线程数大于等于核心线程数:
- 如果阻塞队列未满,则将任务放入阻塞队列中。
- 如果阻塞队列已满:
- 如果线程池中的线程数小于最大线程数,则创建一个新线程来执行当前任务。
- 如果线程池中的线程数大于等于最大线程数,则执行拒绝策略。
基于上述流程,当corePoolSize设置为0时,任务是否会直接进入阻塞队列等待执行?如果队列足够大,任务是否可能因为队列未满而永远无法执行(因为没有空闲线程被创建)?
实践出真知
猜测无益,实践才是检验真理的唯一标准。下面我配置了一个线程池,希望在提交任务时,能够通过“空闲线程”快速处理任务,然后自动销毁,不占用系统资源。那么,这种配置的线程池是否可能因为阻塞队列未满而导致任务迟迟不被执行?
private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
0,
8,
5, TimeUnit.MINUTES,
new LinkedBlockingQueue<>(512),
new CallerRunsPolicy()
);
我们使用这个线程池来打印一个字符串,以验证任务是否能够被执行。
public static void main(String[] args) {
MonitorThreadPoolConfig.addThreadPoolExecutor(threadPoolExecutor);
threadPoolExecutor.execute(() -> System.out.println("hahahhaha "));
}
执行结果显示:任务确实被执行了(这里我添加了对线程池的定时监控)。
深入源码
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* 执行分为三个步骤:
*
* 1. 如果运行的线程数少于核心线程数,尝试
* 用给定的命令作为其第一个任务启动一个新线程。
* addWorker原子检查runState和workerCount,
* 因此可以防止在不应该添加线程时添加线程。
*
* 2. 如果任务可以成功入队,那么我们仍然需要
* 再次检查是否应该添加一个线程(因为现有的线程可能已经死亡)
* 或者池是否已经关闭。因此,如果停止了,我们需要回滚入队操作,
* 或者如果没有线程,就启动一个新线程。
*
* 3. 如果我们不能将任务入队,那么我们尝试添加一个新线程。
* 如果失败,我们知道我们已经关闭或者饱和了,
* 因此拒绝任务。
*/
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
}
从源码的第34行到第35行可以看出:当核心线程数为0时,会创建一个新的线程来执行当前任务。
进一步探讨
既然可以通过设置corePoolSize为0来最小化“常驻”线程的资源占用,那么是否有其他方法可以达到相同的效果呢?
有经验的开发者可能会立刻回答:从Java 1.6开始,ThreadPoolExecutor有一个属性可以实现核心线程超时销毁的功能。
/**
* 如果设置为false(默认),即使空闲,核心线程也会保持活动状态。
* 如果设置为true,核心线程将使用keepAliveTime来超时等待工作。
*/
private volatile boolean allowCoreThreadTimeOut;
我们可以将线程池配置如下
文章整理自互联网,只做测试使用。发布者:Lomu,转转请注明出处:https://www.it1024doc.com/4405.html