java 优雅关闭线程池的方案

作者:AnonyStar 时间:2022-03-20 23:05:44 

我们经常在项目中使用的线程池,但是是否关心过线程池的关闭呢,可能很多时候直接再项目中直接创建线程池让它一直运行当任务执行结束不在需要了也不去关闭,这其实是存在非常大的风险的,大量的线程常驻在后台对系统资源的占用是巨大的 ,甚至引发异常。所以在我们平时使用线程池时需要注意优雅的关闭,这样可以保证资源的管控。

在 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

  • 当调用了shutDown 或shutDownNow 时之后,会返回 true 不过需要注意,这时候只是代表线程池关闭流程的开始,并不是说线程池已经停止了

isTerminated

  • 这个方法与上面的方法的区别就是这是正真检测线程池是否真的终结了

  • 这不仅代表线程池已关闭,同时代表线程池中的所有任务都已经都执行完毕了,因为在调用 shutdown方法之后,线程池会继续执行里面未完成的任务,包括正在执行的任务和在任务队列中等待的任务。

  • 如果调用了 shutdown 方法,但是有一个线程依然在执行任务,那么此时调用 isShutdown方法返回的是 true,而调用 isTerminated方法返回的便是 false,因为线程池中还有任务正在在被执行,线程池并没有真正“终结”。

  • 直到所有任务都执行完毕了,调用 isTerminated()方法才会返回 true,这表示线程池已关闭并且线程池内部是空的,所有剩余的任务都执行完毕了。

作者:AnonyStar

原文链接:https://www.cnblogs.com/i-code/p/14024845.html

来源:https://www.cnblogs.com/i-code/p/14024845.html

标签:java,关闭,线程池
0
投稿

猜你喜欢

  • 在Maven下代理服务器设定的方式

    2023-10-15 02:17:13
  • 全局记录Feign的请求和响应日志方式

    2021-08-19 18:48:02
  • JavaWeb建立简单三层项目步骤图解

    2023-03-08 16:51:02
  • springboot的yml配置文件通过db2的方式整合mysql的教程

    2023-08-06 04:28:55
  • JPA多数据源分布式事务处理方案

    2023-08-09 03:50:06
  • SpringBoot如何集成PageHelper分页功能

    2022-10-22 03:18:34
  • java开发之内部类的用法

    2023-02-04 21:30:07
  • SpringMVC数据响应详细介绍

    2023-09-24 04:12:41
  • Android布局之帧布局FrameLayout详解

    2023-08-07 04:45:29
  • java如何导出insert语句并生成sql脚本

    2022-05-18 10:33:54
  • SpringBoot文件上传大小设置方式(yml中配置)

    2021-09-21 09:26:47
  • Flutter 通过Clipper实现各种自定义形状的示例代码

    2023-06-19 14:25:11
  • 浅析JDK12的五大重要新特性(推荐)

    2023-01-28 19:09:24
  • linux下idea、pycharm等输入中文拼音时满3个字母后无法继续拼音输入的问题

    2022-03-03 20:49:19
  • TransmittableThreadLocal解决线程间上下文传递烦恼

    2023-11-09 17:09:35
  • Spring Cache简单介绍和使用大全

    2023-11-25 04:46:46
  • Java对象类型的判断详解

    2023-07-26 09:55:07
  • Springboot JPA 枚举Enum类型存入到数据库的操作

    2023-11-25 16:11:40
  • 解决idea web 配置相对路径问题

    2022-01-12 06:48:40
  • Java中的main函数的详细介绍

    2021-10-03 16:09:16
  • asp之家 软件编程 m.aspxhome.com