ThreadPoolExecutor 的关闭流程很简单
void shutdown()
1. 获取 mainLock 锁
2. 当前的状态如果是 SHUTDOWN ,STOP ,TIDYING ,TERMINATED 则退出
3. 如果不是则 CAS 设置状态为 SHUTDOWN
4. CAS 失败则回到 step 2 继续
5. 对所有 Worker 线程调用 interrupt() 中断阻塞
6. 释放 mainLock ,调用 tryTerminate() 关闭线程池
step 5 中断所有线程后,新的任务不能再提交进来,但是 worker 线程并不会立即退出,会继续从 workQueue 取出并执行任务,直到没有任务后再退出。所以调用 shutdown() 的线程在这里不会被阻塞,线程池会等待 workQueue 里面所有任务执行完毕以后才会变成 TERMINATED。
void tryTerminate()
1. 获取当前的线程数量,线程池状态
2. 如果线程池状态是 RUNNING、 TIDYING、 TERMINATED 直接返回
3. 如果线程池是 SHUTDOWN,但是 workQueue 还有 task,直接返回
4. 到这步,线程池状态应该是 SHUTDOWN 并且 workQueue 已经没有 task,或者是 STOP。如果线程池里面还有线程存活,call interruptIdleWorkers(true) 从 workers 里面去关闭一个闲置线程 (为什么只关闭一个?),return
5. 到这步,线程池状态应该是 SHUTDOWN 或者 STOP,workQueue 已经没有 task,线程池里面没有线程存活。获取 mainLock, CAS 操作设置状态为 TIDYING 。如果 CAS 成功,则再次设置状态为 TERMINATED, call termination.signalAll()唤醒等待线程池关闭的线程(外部线程可能 call awaitTermination(long timeout, TimeUnit unit)等待线程池彻底关闭)
6. 释放mainLock
这里的疑惑为 step 4,当线程池里面还有线程存活的时候,尝试去关闭最多一个线程。为什么是只关闭最多一个?而不是全部?注意 step 5,CAS操作设置状态为 TIDYING 。这是因为前面检查状态都是在没获取 mainLock 情况下完成的,在获取 mainlock 后重复检查成功,之后才设置 TERMINATED 状态并唤醒等待线程池关闭的线程
List<Runnable> shutdownNow()
1. 获取 mainLock 锁
2. 当前的状态如果是 STOP ,TIDYING ,TERMINATED 则退出
3. 如果不是则 CAS 设置状态为 STOP
4. CAS 失败则回到 step 2 继续
5. 对所有 Worker 线程调用 interrupt() 中断阻塞
6. 从 workQueue 里面取出所有任务,
7. 释放 mainLock ,调用 tryTerminate() 关闭线程池。返回 workQueue 里没有被执行的任务。
shutdownNow() 和 shutdown() 流程很类似,但是调用后不会等待 Worker 线程继续执行已经提交任务。相反,当前调用线程会取出任务返回。
boolean awaitTermination(long timeout, TimeUnit unit)
1. 获取 mainLock 锁
2. 当前的状态如果是 TERMINATED 则返回 true
3. 如果不是,使用和 mainLock 关联的条件 termination.awaitNanos(nanos) 等待 指定时间,超时后状态还不是 TERMINATED。 返回false。
4. 释放 mainLock 锁
调用 awaitTermination 的线程会被阻塞最多指定时间,最后是否关闭线程池成功需要判断返回值。
Java ThreadPoolExecutor 学习笔记(一)
Java ThreadPoolExecutor 学习笔记(二)
分享到:
相关推荐
主要介绍了java ThreadPoolExecutor使用方法简单介绍的相关资料,需要的朋友可以参考下
(转)线程池:java_util_ThreadPoolExecutor 比较详细的介绍了ThreadPoolExecutor用法与属性
在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面是线程的创建更加规范,可以合理控制开辟线程的数量;另一方面线程的细节管理交给线程池处理,优化了...
主要介绍了java ThreadPoolExecutor 并发调用实例详解的相关资料,需要的朋友可以参考下
提供工厂方法来创建不同类型的线程池,这篇文章主要介绍了Java ThreadPoolExecutor 线程池的使用介绍,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来...
ThreadPoolExecutor使用和思考
一个关于java 线程池的例子,也适合android
Java分布式应用学习笔记07线程池应用
主要介绍了Java ThreadPoolExecutor的参数深入理解的相关资料,需要的朋友可以参考下
JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor)使用
主要介绍了java中Executor,ExecutorService,ThreadPoolExecutor详解的相关资料,需要的朋友可以参考下
Java多线程实现数据切割批量执行,实现限流操作。 java线程池Executors实现数据批量操作。 批量异步Executors处理数据,实现限流操作,QPS限流。 线程池调用第三方接口限流实现逻辑。 案例适合: 1.批量处理大数据。...
Java并发编程 背景介绍 并发历史 必要性 进程 资源分配的最小单位 线程 CPU调度的最小单位 线程的优势 (1)如果设计正确,多线程程序可以通过提高处理器资源的利用率来提升系统吞吐率 ...
——学习参考资料:仅用于个人学习使用! 本代码仅作学习交流,切勿用于商业用途,否则后果自负。若涉及侵权,请联系,会尽快处理! 未进行详尽测试,请自行调试!
ThreadPoolExecutor源码解析.pdf
主要介绍了java 中ThreadPoolExecutor原理分析的相关资料,需要的朋友可以参考下
ThreadPoolExecutor源码解析.md
主要介绍了java中ThreadPoolExecutor常识汇总,线程池技术在并发时经常会使用到,java中的线程池的使用是通过调用ThreadPoolExecutor来实现的,需要的朋友可以参考下
ThreadPoolExecutor线程池,有详尽介绍,本人进行过测试,可以使用
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long