189 8069 5689

java如何使用ExecutorService关闭线程池?-创新互联

ExecutorService让我们可以优雅地在程序中使用线程池来创建和管理线程,而且性能佳、开销小,还可以有效地控制大并发线程数,是我们在java并发编程中会经常使用到的。

创新互联自2013年创立以来,是专业互联网技术服务公司,拥有项目成都网站设计、成都网站制作网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元万州做网站,已为上家服务,为万州各地企业和个人服务,联系电话:18980820575

每一个线程都会占用系统资源,因此线程池的关闭与清理同样重要,本文介绍我们如何优雅地关闭线程池。

一. ExecutorService中关闭线程池的方法

1. shutdown()

停止接收新任务,原来的任务继续执行

  1. 停止接收新的submit的任务;
  2. 已经提交的任务(包括正在跑的和队列中等待的),会继续执行完成;
  3. 等到第2步完成后,才真正停止;

2. shutdownNow()

停止接收新任务,原来的任务停止执行

  1. 跟 shutdown() 一样,先停止接收新submit的任务;
  2. 忽略队列里等待的任务;
  3. 尝试将正在执行的任务interrupt中断;
  4. 返回未执行的任务列表;

    说明:它试图终止线程的方法是通过调用 Thread.interrupt() 方法来实现的,这种方法的作用有限,如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt() 方法是无法中断当前的线程的。所以,shutdownNow() 并不代表线程池就一定立即就能退出,它也可能必须要等待所有正在执行的任务都执行完成了才能退出。但是大多数时候是能立即退出的。

3. awaitTermination(long timeOut, TimeUnit unit)

当前线程阻塞,timeout 和 TimeUnit 两个参数,用于设定超时的时间及单位,当前线程阻塞,直到:

  • 等所有已提交的任务(包括正在跑的和队列中等待的)执行完;
  • 或者 等超时时间到了(timeout 和 TimeUnit设定的时间);
  • 或者 线程被中断,抛出InterruptedException

然后会监测 ExecutorService 是否已经关闭,返回true(shutdown请求后所有任务执行完毕)或false(已超时)

二. 三种方法的区别

1. shutdown() 和 shutdownNow() 的区别

  • shutdown() 只是关闭了提交通道,用submit()是无效的;而内部该怎么跑还是怎么跑,跑完再停。
  • shutdownNow() 能立即停止线程池,正在跑的和正在等待的任务都停下了。

2. shutdown() 和 awaitTermination() 的区别

  • shutdown() 后,不能再提交新的任务进去;但是 awaitTermination() 后,可以继续提交。
  • awaitTermination() 是阻塞的,返回结果是线程池是否已停止(true/false);shutdown() 不阻塞。

3. 总结

  1. 优雅的关闭,用 shutdown()
  2. 想立马关闭,并得到未执行任务列表,用shutdownNow()
  3. 优雅的关闭,并允许关闭声明后新任务能提交,用 awaitTermination()
  4. 关闭功能 【从强到弱】 依次是:shuntdownNow() > shutdown() > awaitTermination()

三. RunTime.getRunTime().addShutdownHook()的作用

RunTime.getRunTime().addShutdownHook()的作用就是在JVM销毁前执行的最后一个线程,通过addShutdownHook添加钩子,当系统执行完这些钩子后,jvm才会关闭,因此我们可以在这个线程中把我们前面使用ExecutorService创建的线程池优雅地关闭掉。
在web3j中异步执行类(Async)中有如下代码:

// 创建线程池
private static final ExecutorService executor = Executors.newCachedThreadPool();

// 添加关闭线程池的钩子
static {
   Runtime.getRuntime().addShutdownHook(new Thread(() - > shutdown(executor)));
}

// 关闭线程池的钩子函数
private static void shutdown(ExecutorService executorService) {
   // 第一步:使新任务无法提交
   executorService.shutdown();
   try {
     // 第二步:等待未完成任务结束
     if(!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
       // 第三步:取消当前执行的任务
       executorService.shutdownNow();
       // 第四步:等待任务取消的响应
       if(!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
         System.err.println("Thread pool did not terminate");
       }
     }
   } catch(InterruptedException ie) {
     // 第五步:出现异常后,重新取消当前执行的任务
     executorService.shutdownNow();
     Thread.currentThread().interrupt(); // 设置本线程中断状态
   }
}

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


新闻标题:java如何使用ExecutorService关闭线程池?-创新互联
网页地址:http://cdxtjz.cn/article/cdeeje.html

其他资讯