代码改变世界

第一章:多线程十三之线程池的关闭

2023-11-01 10:29  阿方技术圈  阅读(54)  评论(0)    收藏  举报

线程池总共存在5种状态,定义在ThreadPoolExecutor类中,具体代码如下:

     package java.util.concurrent;
     // 省略import
     public class ThreadPoolExecutor extends AbstractExecutorService {
          // runState is stored in the high-order bits
         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;
         // 省略其他
     }

  线程池的5种状态具体如下:

1)RUNNING:线程池创建之后的初始状态,这种状态下可以执行任务。

(2)SHUTDOWN:该状态下线程池不再接受新任务,但是会将工作队列中的任务执行完毕。

(3)STOP:该状态下线程池不再接受新任务,也不会处理工作队列中的剩余任务,并且将会中断所有工作线程。

(4)TIDYING:该状态下所有任务都已终止或者处理完成,将会执行terminated()钩子方法。

(5)TERMINATED:执行完terminated()钩子方法之后的状态。

线程池的状态转换规则为:

(1)线程池创建之后状态为RUNNING。

(2)执行线程池的shutdown()实例方法,会使线程池状态从RUNNING转变为SHUTDOWN。

(3)执行线程池的shutdownNow()实例方法,会使线程池状态从RUNNING转变为STOP。

(4)当线程池处于SHUTDOWN状态时,执行其shutdownNow()方法会将其状态转变为STOP。

(5)等待线程池的所有工作线程停止,工作队列清空之后,线程池状态会从STOP转变为TIDYING。

(6)执行完terminated()钩子方法之后,线程池状态从TIDYING转变为TERMINATED。

 

关闭线程池主要涉及的方法有3个:

(1)shutdown:是JUC提供的一个有序关闭线程池的方法,此方法会等待当前工作队列中的剩余任务全部执行完成之后,才会执行关闭,但是此方法被调用之后线程池的状态转为SHUTDOWN,线程池不会再接收新的任务。

(2)shutdownNow:是JUC提供的一个立即关闭线程池的方法,此方法会打断正在执行的工作线程,并且会清空当前工作队列中的剩余任务,返回的是尚未执行的任务。

(3)awaitTermination:等待线程池完成关闭。在调用线程池的shutdown()与shutdownNow()方法时,当前线程会立即返回,不会一直等待直到线程池完成关闭。如果需要等到线程池关闭完成,可以调用awaitTermination()方法。

 

关闭线程池的方法

package com.heima.activiti.lhf;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

public class ThreadUtil {

public static void shutdownThreadPoolGracefully(ExecutorService threadPool){
    
    //若已经关闭则返回
    if(!(threadPool instanceof ExecutorService) || threadPool.isTerminated()){
        
        return;
    }
    
    threadPool.shutdown();//拒绝接受新任务
    try {
        //等待60秒,等待线程池中的任务完成执行
        if(!threadPool.awaitTermination(60, TimeUnit.SECONDS)){
            threadPool.shutdownNow();
            if(!threadPool.awaitTermination(60, TimeUnit.SECONDS)){
                System.out.print("线程池任务未正常执行结束");
            }
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
        threadPool.shutdownNow();
    }
    
    if(!threadPool.isTerminated()){
        for (int i = 0;i<1000;i++){
            try {
                if(!threadPool.awaitTermination(10, TimeUnit.SECONDS)){
                    break;
                }
                threadPool.shutdownNow();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
           
        }
    }
}
}