1. 线程池是何时建立线程的?java
2. 任务runnable task是先放到core到maxThread之间的线程,仍是先放到队列?ide
3. 队列中的任务是何时取出来的?源码分析
4. 何时会触发reject策略?spa
5. core到maxThread之间的线程何时会die?线程
6. task抛出异常,线程池中这个work thread还能运行其余任务吗?3d
先写一段基础代码,进入分析调试
public static void main(String[] args) {
ExecutorService executorService = new ThreadPoolExecutor(2, 5, 0, TimeUnit.DAYS,
new ArrayBlockingQueue<>(1), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
// thread.setDaemon(true);
return thread;
}
});
// 对象建立后,线程实际还没开始建立
// 执行execute时,检查当前池中线程数大小是否小于core number, 若是是,则建立新线程
executorService.execute(() -> {
System.out.println("任务1@" + Thread.currentThread().getName());
sleepTime();
System.out.println(1);
});
//检查当前池中线程数大小是否小于core number, 若是是,则建立新线程
executorService.execute(() -> {
System.out.println("任务2@" + Thread.currentThread().getName());
sleepTime();
System.out.println(2);
});
// 检查当前池中线程数大小是否小于core number, 若是不是,则偿试放入队列
// 这个任务是加到队列去的, 注意队列大小只有1,
// TODO 队列中的任务是何时取出来的? 任务1或者2结束后所占用的线程 会运行队列中的任务,这个任务是在最后才运行,比4运行的还晚
executorService.execute(() -> {
System.out.println("任务3@" + Thread.currentThread().getName());
sleepTime();
System.out.println(3);
});
// 检查当前池中线程数大小是否小于core number, 若是不是,则偿试放入队列,放入队列也失败,则增长新的worker线程
// 这个任务是加到core之外的新线程去的
executorService.execute(() -> {
System.out.println("任务4@" + Thread.currentThread().getName());
sleepTime();
System.out.println(4);
});
}
注意第3行,建立一个核心池2, 最大池5, 队列为1的线程池对象
至少在new ThreadPoolExecutor()时,Thread对象并无初始化. 这里仅仅指定了几个初始参数blog
执行第一个execute时,进入调试jdk源码队列
代码块1
第一个if, 判断若是当前线程数小于corePoolSize, 则建立新的核心worker对象(Worker中指向Thread对象,保持引用,保证不会被GC回收)
咱们的示例代码中,第1和第2个任务都是这样建立出线程的
第二个if, 判断若是当前线程数大于corePoolSize, 并偿试放入队列 workQueue.offer(command) , 放入成功后等待线程池调度【见后面的getTask()】
示例代码中,第3个任务是这样等待调度的,最后才执行
第三个if, 偿试放入队列 workQueue.offer(command) 失败, 增长一个非core的线程
示例代码中,第4个任务是这样开始的
而后再看addWorker()的过程
new Worker构造和线程启动
线程启动后,又作了哪些工做:
没抛异常时,此线程会一直在while(task !=null || (task = getTask())!=null)中跑
那么有异常时,再看一下processWorkerExit
能够 看出,有异常时 旧的worker会被删除(GC回收),再建立新的Worker, 即有异常时 旧worker不可能再执行新的任务
Q. 线程池是何时建立线程的?
A.任务提交的时候
Q.任务runnable task是先放到core到maxThread之间的线程,仍是先放到队列?
A.先放队列!!!
Q. 队列中的任务是何时取出来的?
A. worker中 runWorker() 一个任务完成后,会取下一个任务
Q. 何时会触发reject策略?
A.队列满而且maxthread也满了, 还有新任务,默认策略是reject
Q. core到maxThread之间的线程何时会die?
A. 没有任务时,或者抛异常时。
core线程也会die的,core到maxThread之间的线程有可能会晋升到core线程区间,
core max只是个计数,线程并非建立后就固定在一个区间了
Q. task抛出异常,线程池中这个work thread还能运行其余任务吗?
A. 不能。 可是会建立新的线程, 新线程能够运行其余task。
对于 schedulerThreadPoolExecutor? 虽然有新线程,可是旧的循环任务不会再继续执行了, 开发实践推荐任务中捕获全部Exception