download:2周刷完100道前端优质面试真题
备链:https://www.sisuoit.com/2566.html
线程池执行流程
想要真正的了解线程池的执行流程,就得先从线程池的执行方法 execute()
说起,execute()
实现源码如下:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
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);
// 如果线程池的线程数为 0 时(当 corePoolSize 设置为 0 时会发生)
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
// 新建线程执行任务
}
// 核心线程都在忙且队列都已爆满,尝试新启动一个线程执行失败
else if (!addWorker(command, false))
// 执行拒绝策略
reject(command);
}
【2周刷完100道前端优质面试真题wumi】从上述源码我们可以看出,当任务来了之后,线程池的执行流程是:先判断当前线程数是否大于核心线程数?如果结果为 false,则新建线程并执行任务;如果结果为 true,则判断任务队列是否已满?如果结果为
false
,则把任务添加到任务队列中等待线程执行,否则则判断当前线程数量是否超过最大线程数?如果结果为 false,则新建线程执行此任务,否则将执行线程池的拒绝策略,线程池拒绝策略 当任务过多且线程池的任务队列已满时,此时就会执行线程池的拒绝策略,线程池的拒绝策略默认有以下 4 种:
- AbortPolicy:中止策略,线程池会抛出异常并中止执行此任务;
- CallerRunsPolicy:把任务交给添加此任务的(main)线程来执行;
- DiscardPolicy:忽略此任务,忽略最新的一个任务;
- DiscardOldestPolicy:忽略最早的任务,最先加入队列的任务。
默认的拒绝策略为 AbortPolicy 中止策略。
DiscardPolicy
忽略此任务,忽略最新的一个任务为例,演示一下拒绝策略的具体使用,实现代码如下:public static void main(String[] args) {
// 任务的具体方法
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("当前任务被执行,执行时间:" + new Date() +
" 执行线程:" + Thread.currentThread().getName());
try {
// 等待 1s
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
// 创建线程,线程的任务队列的长度为 1
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1,
100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1),
new ThreadPoolExecutor.DiscardPolicy());
// 添加并执行 4 个任务
threadPool.execute(runnable);
threadPool.execute(runnable);
threadPool.execute(runnable);
threadPool.execute(runnable);
// 线程池执行完任务,关闭线程池
threadPool.shutdown();
}
以上程序的执行结果如下:
从上述执行结果可以看出,给线程池添加了 4 个任务,而线程池只执行了 2 个任务就结束了,其他两个任务执行了拒绝策略
DiscardPolicy
被忽略了,这就是拒绝策略的作用。AbortPolicy拒绝策略 为了和
DiscardPolicy
拒绝策略对比,我们来演示一下 JDK 默认的拒绝策略 AbortPolicy
中止策略,线程池会抛出异常并中止执行此任务,示例代码如下:public static void main(String[] args) {
// 任务的具体方法
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("当前任务被执行,执行时间:" + new Date() +
" 执行线程:" + Thread.currentThread().getName());
try {
// 等待 1s
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
// 创建线程,线程的任务队列的长度为 1
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1,
100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1),
new ThreadPoolExecutor.AbortPolicy());
// 显式指定拒绝策略,也可以忽略此设置,它为默认拒绝策略
// 添加并执行 4 个任务
threadPool.execute(runnable);
threadPool.execute(runnable);
threadPool.execute(runnable);
threadPool.execute(runnable);
// 线程池执行完任务,关闭线程池
推荐阅读
- JavaScript|什么,BOM指的是物料清单()
- 应用数据同步自动化指导文档
- CS 120 Style and Errors
- 笔记|Vue原理深度剖析
- javascript|Vue2 原理浅谈
- 前端|深入理解vue 一些底层原理
- 前端面试总结|vue核心面试题(vue中模板编译原理)
- Vue|Vue2的核心原理剖析
- Code Review最佳实践