如何正确关闭线程池

如何正确关闭线程池
首先有5种在ThreadPoolExecutor中涉及的关闭线程的方法,我们挨个来分析。

 

void shutdown()

    它可以安全的关闭一个线程池,调用shutdown()方法后,线程池不会立刻关闭,而是等执行完正在执行的任务和队列中等待的任务后才彻底关闭,而且调用shutdown()方法后,如果还有新的任务继续到来,那么线程池会根据拒绝策略直接拒绝后面来的新任务.

 

boolean isShutdown()

    这个方法可以返回ture或者false来判断是否已经开始了关闭工作,也就是是否执行了shutdown或者shutdownNow方法,调用isShutdown()方法后如果返回true,并不代表线程池已经彻底关闭了,仅仅代表开始了关闭流程,仍然可能有线程正在执行任务,队列里也可能有任务等待被执行.

 

boolean isTerminated()

    这个方法可以检测是否真正关闭了,不仅代表线程池是否已经关闭,同时也代表线程池中的所有任务是否已经都执行完毕,比如已经调用了shutdown()方法,但是有一个线程正在执行任务,则此时调用isShutdown方法返回true,而调用isTerminated方法便返回false,,因为线程池中还有任务再执行,线程池没有真正关闭,直到所有线程都执行完毕,任务都执行完毕,再调用isTermainted就返回ture.

 

boolean awaitTermination(long timeout,TimeUnit unit),throws IntereuptedException

     awaitTermination并不是用来关闭线程池的,而是用来判断线程池状态的,参数需要传入一个时间,如果我们设置10秒钟,那么会有以下几种情况:

  • 等待期间,线程池已经关闭且所有提交的任务都执行完毕,那么方法就返回ture,相当于线程池真正关闭了.
  • 等待时间超时后,第一种情况未发生,那么方法返回false.
  • 等待时间中,执行任务的线程被中断了,方法会抛出InterruptedException异常.

所以综上可以看出,调用 awaitTermination 方法后当前线程会尝试等待一段指定的时间,如果在等待时间内,线程池已关闭并且内部的任务都执行完毕了,也就是说线程池真正“终结”了,那么方法就返回 true,否则超时返回 fasle,我们则可以根据 awaitTermination() 返回的布尔值来判断下一步应该执行的操作。

 

List<Runnable> shutdownNow()

    调用shutdownNow()方法后,首先会给所有线程池中的线程发送interrupt中断信号,尝试中断这些任务的执行,

    然后就任务队列中在等待被执行的任务转移到一个List中并返回,我们可以再根据List做一些操作,shutdownNow() 的源码如下所示:

public List<Runnable> shutdownNow() {
    List<Runnable> tasks;
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        checkShutdownAccess();
        //转换线程运行状态
        advanceRunState(STOP);
        //让每一个已经启动的线程都中断,如果被中断的线程对于中断信号不理不睬
        //那么依然有可能导致任务不会停止
        interruptWorkers();
        //将队列中任务放入tasks集合中,并返回.
        tasks = drainQueue();
    } finally {
        mainLock.unlock();
    }
    tryTerminate();
    return tasks;
}

 

posted @ 2022-11-24 10:09  weslie  阅读(880)  评论(0编辑  收藏  举报