- 难度:中级
- 开发语言:Java
- 学习时间:20分钟
1.线程池状态
线程池一共有五种状态:
- RUNNING
- SHUTDOWN
- STOP
- TIDYING
- TERMINATED
状态解析:
- RUNNING:线程池正常运行。
- SHUTDOWN:调用 shutdown 方法后,将线程池状态设置为此值,所有空闲线程都将被中断。不再接收新任务,也不再添加新线程。
- STOP:调用 shutdownNow 方法后,将线程池状态设置为此值,所有线程都将被中断。不再接收新任务,也不再添加新线程。
- TIDYING:线程池处于此状态时,任务队列为空,线程数为 0。
- TERMINATED:线程池处于此状态时,表示线程池已关闭。
源码:
private static final int RUNNING = -1 << COUNT_BITS;private static final int SHUTDOWN = 0 << COUNT_BITS;private static final int STOP = 1 << COUNT_BITS;private static final int TIDYING = 2 << COUNT_BITS;private static final int TERMINATED = 3 << COUNT_BITS;
用于记录线程池状态的属性:
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
2.判断线程池状态的方法
公开的:
- boolean isShutdown()
- boolean isTerminating()
- boolean isTerminated()
私有的:
- isRunning(int c)
- boolean isStopped()
3.isRunning(int c) 方法源码分析
/** * 判断线程池状态是否为RUNNING * * @param c ctl值。 */private static boolean isRunning(int c) { // 判断 ctl 值是否小于 SHUTDOWN // true:是 // false:不是/** return c < SHUTDOWN;}
4.boolean isStopped() 方法源码分析
/** * 判断线程池状态是否为STOP */boolean isStopped() { // 判断 ctl值是否大于或等于STOP // true:是STOP状态。 // false:不是STOP状态。 return runStateAtLeast(ctl.get(), STOP);}
5.boolean isShutdown() 方法源码分析
/** * 判断线程池是否开始关闭。 */public boolean isShutdown() { // 判断 ctl值是否大于或等于SHUTDOWN // true:是SHUTDOWN状态。 // false:不是SHUTDOWN状态。 return runStateAtLeast(ctl.get(), SHUTDOWN);}
6.boolean isTerminating() 方法源码分析
/** * 判断线程池是否正在关闭。 */public boolean isTerminating() { // 获取当前线程池状态。 int c = ctl.get(); // runStateAtLeast(c, SHUTDOWN):当前线程池状态值 >= SHUTDOWN // runStateLessThan(c, TERMINATED):当前线程池状态值 < TERMINATED // 综上所述,SHUTDOWN <= 当前线程池状态值 < TERMINATED,即SHUTDOWN、STOP、TIDYING。 return runStateAtLeast(c, SHUTDOWN) && runStateLessThan(c, TERMINATED);}
7.boolean isTerminated() 方法源码分析
/** * 判断线程池是否已关闭。 */public boolean isTerminated() { // 当当前线程池状态 >= TERMINATED时,表示线程池已关闭。 return runStateAtLeast(ctl.get(), TERMINATED);}
8.示例
package com.gorhaf;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class Main { public static void main(String[] args) throws InterruptedException { // 创建线程池 ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 20, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); // 观察线程池情况 watching(threadPool); // 提交任务 threadPool.submit(createTask()); // 关闭线程池 threadPool.shutdown(); } /** * 创建任务 * * @return 任务 */ private static Runnable createTask() { // 创建任务 Runnable task = new Runnable() { @Override public void run() { try { // 模拟耗时任务 TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } }; return task; } /** * 观察线程池内部情况 * * @param threadPool 线程池 */ private static void watching(ThreadPoolExecutor threadPool) { Runnable task = new Runnable() { @Override public void run() { for (; ; ) { try { System.out.println("线程池是否开始关闭:" + threadPool.isShutdown() + ",正在关闭:" + threadPool.isTerminating() + ",已关闭:" + threadPool.isTerminated()); // 每经过1秒钟获取一次线程池信息 TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } }; new Thread(task).start(); }}
运行结果:
文字版:
线程池是否开始关闭:false,正在关闭:false,已关闭:false线程池是否开始关闭:true,正在关闭:true,已关闭:false线程池是否开始关闭:true,正在关闭:false,已关闭:true线程池是否开始关闭:true,正在关闭:false,已关闭:true线程池是否开始关闭:true,正在关闭:false,已关闭:true
刚开始,线程池没有关闭,所有结果都为 false。
接着,调用 threadPool.shutdown() 关闭线程池,还没完成的任务继续执行,等线程池中所有任务都完成再关闭,isShutdown() 和 isTerminating() 都返回true,isTerminated() 返回 false。
最后,线程池里都任务都完成,线程池也可以彻底关闭了,isShutdown() 和 isTerminated() 都返回true,isTerminating() 返回 false。
总结
- 线程池一共有五种状态:
- RUNNING
- SHUTDOWN
- STOP
- TIDYING
- TERMINATED
- RUNNING:线程池正常运行。
- SHUTDOWN:调用 shutdown 方法后,将线程池状态设置为此值,所有空闲线程都将被中断。不再接收新任务,也不再添加新线程。
- STOP:调用 shutdownNow 方法后,将线程池状态设置为此值,所有线程都将被中断。不再接收新任务,也不再添加新线程。
- TIDYING:线程池处于此状态时,任务队列为空,线程数为 0。
- TERMINATED:线程池处于此状态时,表示线程池已关闭。
- boolean isShutdown() 判断线程池是否开始关闭。
- boolean isTerminating() 判断线程池是否正在关闭。
- boolean isTerminated() 判断线程池是否已关闭。
答疑
如果大家有任何疑问,请在下方留言或评论。
上一章
Java线程池核心(十):从源码上分析shutdown与shutdownNow区别
下一章
Java线程池核心(十二):提交任务后做了什么?
学习小组
加入同步学习小组,共同交流与进步。
欢迎加入“人人都是程序员”编程圈子,与圈友一起交流讨论。