背景
为了方便测试,设置核心线程数(corePoolSize)为2,最大线程数(maximumPoolSize)为3,任务队列长度为3。
构建测试环境
创建一个线程池,任务执行时长通过doSomeThing的sleep时长来决定。
public static void testThreadPoolExecutor(int listSize) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 5, 10L,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(3));
if (listSize <= 0){
return;
}
try {
for (int i = listSize; i > 0; i--) {
executor.execute(() -> doSomeThing());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executor.shutdown();
while (true) {
if (executor.isTerminated()) {
break;
}
}
}
}
private static void doSomeThing() {
try {
Thread.sleep(1);
}catch (Exception e){
}
}
问题1
启动线程池,还未提交任务,此时线程池有几个线程?
答:0个,debug可以看出,创建线程池后,并没有往线程池添加线程。
问题2
提交第一个任务,待第一个任务执行完成之后,再提交第二个任务,此时线程池有几个线程?即在第一个任务执行完成后,提交第二个任务,是否会创建新线程?
答:会创建新线程
源码的注释上写到
When a new task is submitted in method {@link #execute(Runnable)},
- and fewer than corePoolSize threads are running, a new thread is
- created to handle the request, even if other worker threads are
- idle
线程数小于核心线程数时,即使其他线程是空闲的,也会创建新的线程
even if other worker threads are idle
将doSomeThing的sleep时长设置为1
debug调试显示,即使前一个任务执行完了,再次提交任务,依旧会创建新的线程
源码中,只判断了当前线程数是否小于核心线程数,并没有校验上一个线程是否空闲状态
问题3
同时提交两个任务,执行时间都超长,此时再提交一个任务,是创建新线程来执行还是将任务提交至任务队列?
将doSomeThing的sleep时长设置为无限大
答:将任务提交至队列 ,直至队列满了,才会继续创建新线程。
源码注释中写道
If there are more than corePoolSize but less than
- maximumPoolSize threads running, a new thread will be created only
- if the queue is full.
如果线程大约核心线程数,且小与最大线程数是,只有队列满了才会创建新的线程
only if the queue is full.
拒绝策略
关于拒绝策略可以参考之前的文章