线程池详细解析(三)
本章我们来讲一讲线程池的最后一个方法shutdown,这个方法的主要作用就是将线程池进行关闭
shutdown:
public void shutdown() {ReentrantLock var1 = this.mainLock;var1.lock();try {this.checkShutdownAccess();this.advanceRunState(0);this.interruptIdleWorkers();this.onShutdown();} finally {var1.unlock();}this.tryTerminate();}
可以看出线程池关闭的这个方法也是获取的全局锁进行上锁处理,我们发现在线程池中很多方法都是需要拿全局锁来进行上锁处理的:线程池关闭,执行任务。。。等方法
随后调用了四个方法
-
权限检查
checkShutdownAccess()
:确保调用者有权限关闭线程池,通常通过安全管理器验证。 -
状态转换
advanceRunState(0)
:将线程池状态设置为SHUTDOWN
(参数 0 对应SHUTDOWN
状态),禁止新任务提交,但会继续执行已提交的任务。 -
中断空闲线程
interruptIdleWorkers()
:中断所有空闲的工作线程,使它们从等待队列中退出,加速关闭过程。 -
触发关闭回调
onShutdown()
:空方法,可被子类重写以实现自定义关闭逻辑,例如资源释放或日志记录。
下面我们一一查看这四个方法
checkShutdownAccess:
private void checkShutdownAccess() {SecurityManager var1 = System.getSecurityManager();if (var1 != null) {var1.checkPermission(shutdownPerm);ReentrantLock var2 = this.mainLock;var2.lock();try {Iterator var3 = this.workers.iterator();while(var3.hasNext()) {Worker var4 = (Worker)var3.next();var1.checkAccess(var4.thread);}} finally {var2.unlock();}}}
checkShutdownAccess这个方法主要是检查是否有权限关闭线程池,从系统中获取到SecurityManager 这个用于管理jvm权限的权限工具,对其进行校验是否有资格shutdown。之后再从workers队列中进行遍历worker对其进行权限检查。总的来说这个方法就是进行权限的校验检查的
advanceRunState:
private void advanceRunState(int var1) {int var2;do {var2 = this.ctl.get();} while(!runStateAtLeast(var2, var1) && !this.ctl.compareAndSet(var2, ctlOf(var1, workerCountOf(var2))));}
这个方法的作用则是通过CAS将线程池的状态置为shutdown状态,这样后续的线程在执行完任务之后会检查线程池状态,如果shutdown状态当任务执行完毕之后则会销毁线程
interruptIdleWorkers:
private void interruptIdleWorkers(boolean var1) {ReentrantLock var2 = this.mainLock;var2.lock();try {Iterator var3 = this.workers.iterator();while(var3.hasNext()) {Worker var4 = (Worker)var3.next();Thread var5 = var4.thread;if (!var5.isInterrupted() && var4.tryLock()) {try {var5.interrupt();} catch (SecurityException var15) {} finally {var4.unlock();}}if (var1) {break;}}} finally {var2.unlock();}}
这个方法的主要作用则是关闭掉那些空闲的线程,一样的获取全局锁然后开始遍历整个线程集合,查找那些空闲线程(即未上锁的线程),查找到之后则直接更改其中断位,后续空闲线程当查询到自己中断后则会跳出循环直接进行销毁线程,而这个方法的参数Boolean类型的作用就是用来标志是否回收一个空闲线程还是回收全部。
onShutdown
而这个方法则是空方法主要用来后置shutdown的钩子函数的,留给子类去实现。