优雅关闭线程池的方案

  • 咱们常常在项目中使用的线程池,可是是否关心过线程池的关闭呢,可能不少时候直接再项目中直接建立线程池让它一直运行当任务执行结束不在须要了也不去关闭,这实际上是存在很是大的风险的,大量的线程常驻在后台对系统资源的占用是巨大的 ,甚至引起异常。因此在咱们平时使用线程池时须要注意优雅的关闭,这样能够保证资源的管控。
  • Java 中和关闭线程池相关的方法主要有以下:java

    • void shutdown()
    • List<Runnable> shutDownNow
    • boolean awaitTermination
    • boolean isShutDown
    • boolean isTerminated
  • 对于这些方法有着不一样的使用和做用,下面咱们真的会这些不一样的方法作详细的介绍。

ShutDown

  • shutDown 方法从字面意思咱们能够看到是中止关闭的意思,咱们先来看下面的一段代码,首先咱们经过 ThreadPoolExecutor 来建立一个容量是10的无界线程池,与 FixedThreadPool 相似的,这里手动建立能够更好地理解线程池的建立。在后咱们提交一千个任务执行,再执行 shutdown 方法进行暂停。
public static void main(String[] args) throws InterruptedException {

        ExecutorService service = new ThreadPoolExecutor(
                10,
                10,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>());

        for (int i = 0; i < 1000; i++) {
            service.submit(() ->{
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    System.out.println("接受中断,不处理~~");
                }
                System.out.println("args = " + Arrays.deepToString(args)+ Thread.currentThread().getName());
            });
        }

        service.shutdown();
    }
  • 咱们能够看到结果因此线程会正常执行结束后再关闭线程池,对于 ShutDown 而言它能够安全的中止一个线程池,它有几个关键点
  • ShutDown 会首先将线程设置成 SHUTDOWN 状态,而后中断全部没有正在运行的线程
  • 正在执行的线程和已经在队列中的线程并不会被中断,说白了就是使用shutDown 方法其实就是要等待全部任务正常所有结束之后才会关闭线程池
  • 调用 shutdown() 方法后若是还有新的任务被提交,线程池则会根据拒绝策略直接拒绝后续新提交的任务。

ShutDownNow

  • 这个方法与上面方法相比较,直观就是 now ,即当即中止任务,
  • 一样是上述案列,略做修改以下,
public static void main(String[] args) throws InterruptedException {

        ExecutorService service = new ThreadPoolExecutor(
                10,
                10,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1000));

        for (int i = 0; i < 1000; i++) {
            service.submit(() ->{
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    System.out.println("接受中断,结束线程~~");
                    //这里响应中断
                    return;
                }
                System.out.println("args = " + Arrays.deepToString(args)+ Thread.currentThread().getName());
            });
        }

      final List<Runnable> runnables = service.shutdownNow();
       System.out.println(runnables);
    }
  • 执行上述代码咱们发现,当执行shutDownNow 方法后,会像所有正在运行的队列通知中断,正在运行的线程接收到中断信号后选择处理,而在队列中的所有取消执行转移到一个list队列中返回,如上述 List<Runnable> runnables ,这里记录了全部终止的线程

awaitTermination

  • 这个方法并非用来关闭线程池的,首先咱们看一下这个方法的定义:
boolean awaitTermination_(_long timeout, TimeUnit unit_)_
  • 能够看到这个方法有两个参数,timeout 表示等待的时间,unit 时间单位
  • 这个方法的做用是,调用后等待timeout时间后,反馈线程池的状态,
  • 等待期间(包括进入等待状态以前)线程池已关闭而且全部已提交的任务(包括正在执行的和队列中等待的)都执行完毕,至关于线程池已经“终结”了,方法便会返回 true
  • 等待超时时间到后,第一种线程池“终结”的状况始终未发生,方法返回 false
  • 等待期间线程被中断,方法会抛出 InterruptedException 异常。
  • 上面代码能够修改来测试,这里再也不粘贴代码

isShutDown

  • isShutDown 方法正如名字,判断线程池是否中止,返回的是 Boolean 类型,若是已经开始中止线程池则返回 true 不然放回false
  • 当调用了shutDownshutDownNow 时以后,会返回 true 不过须要注意,这时候只是表明线程池关闭流程的开始,并非说线程池已经中止了

isTerminated

  • 这个方法与上面的方法的区别就是这是正真检测线程池是否真的终结了
  • 这不只表明线程池已关闭,同时表明线程池中的全部任务都已经都执行完毕了,由于在调用 shutdown 方法以后,线程池会继续执行里面未完成的任务,包括正在执行的任务和在任务队列中等待的任务。
  • 若是调用了 shutdown 方法,可是有一个线程依然在执行任务,那么此时调用 isShutdown 方法返回的是 true,而调用 isTerminated方法返回的即是 false,由于线程池中还有任务正在在被执行,线程池并无真正“终结”。
  • 直到全部任务都执行完毕了,调用 isTerminated() 方法才会返回 true,这表示线程池已关闭而且线程池内部是空的,全部剩余的任务都执行完毕了。


本文由AnonyStar 发布,可转载但需声明原文出处。
欢迎关注微信公帐号 :云栖简码 获取更多优质文章
更多文章关注笔者博客 : 云栖简码 i-code.online
相关文章
相关标签/搜索