利用JVM钩子函数优雅关闭线程池

核心API:

  • shutDown
  • shutDownNow
  • awaitTermination

利用JVM钩子函数,在虚拟机关闭时调用相关方法即”优雅关闭线程池”。

先通过shutdown等待线程池自身结束,然后等待一段时间,如果没有成功,再调用shutdownNow将等待I/O的任务中断并退出。


    /**
     * 添加钩子函数
     */
    private void initGracefullyShutDown() {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> shutDownThreadPool(asyncExecutor, "BASE")));
        aliasExecutors.forEach((alias, threadPoolExecutor) ->
                Runtime.getRuntime().addShutdownHook(new Thread(() -> shutDownThreadPool(threadPoolExecutor, alias)))
        );
    }

    /**
    * 优雅关闭线程池。
    *  自身关闭,await 60s,强制关闭。
    */
    private void shutDownThreadPool(ExecutorService threadPool, String alias) {
        log.info("Start to shutdown the thead pool : {}", alias);

        threadPool.shutdown();
        try {
            if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
                threadPool.shutdownNow();
                log.warn("Interrupt the worker, which may cause some task inconsistent");

                if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
                    log.warn("Thread pool can't be shutdown even with interrupting worker threads, which may cause some task inconsistent.");
                }
            }
        } catch (InterruptedException ie) {
            threadPool.shutdownNow();
            log.warn("The current server thread is interrupted when it is trying to stop the worker threads. This may leave an inconsistent state.");

            Thread.currentThread().interrupt();
        }
    }

备注:本来是循环调用shutDownThreadPool()方法, 后来发现阻塞严重,追了下源码修改成了循环添加钩子了,具体看如下。

JVM钩子函数

自身没有细追源码,简单看了几篇其他伙伴记录的博客。

  • 虚拟机退出 :JVM会在所有非守护(后台)线程关闭后才会退出 (关于守护线程,随便看了几篇博客回忆下,这篇还不错。《大白话讲解守护线程》)
  • 系统调用System.exit(0)
  • JVM正常退出(Linux上kill命令也会调用钩子函数)

追了一下源码,看了下,发现是一个集合维护Threads。(即咱们调用API,add进去的)

ApplicationShutdownHooks.java

    /* Iterates over all application hooks creating a new thread for each
     * to run in. Hooks are run concurrently and this method waits for
     * them to finish.

     */
    static void runHooks() {
        Collection threads;
        synchronized(ApplicationShutdownHooks.class) {
            threads = hooks.keySet();
            hooks = null;
        }

        for (Thread hook : threads) {
            hook.start();
        }
        for (Thread hook : threads) {
            while (true) {
                try {
                    hook.join();
                    break;
                } catch (InterruptedException ignored) {
                }
            }
        }
    }
}

Original: https://www.cnblogs.com/deepSleeping/p/14976815.html
Author: DeepSleeping丶
Title: 利用JVM钩子函数优雅关闭线程池

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/574537/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • jdk1.8使用枚举类

    package com.mq; import java.util.Arrays; import java.util.HashMap; import java.util.Map; p…

    Java 2023年5月30日
    077
  • 谈谈高并发系统的一些解决方案

    本文结合项目经验,整理一份大纲,供参考。 常用指标 RT(Response Time):响应时间。可能会衍生出 TP999、TP99、TP95、TP90等指标。一般在几毫秒到几百毫…

    Java 2023年6月16日
    070
  • Redis基本操作

    windows 下载 https://github.com/microsoftarchive/redis/releases/tag/win-3.2.100 然后解压 打开服务 然后…

    Java 2023年6月7日
    057
  • 程序员你是如何使用镜像中心Harbor的?

    背景 harbor即docker的私服;管理公司内部输出的镜像制品; 是VMware公司中国团队为企业用户设计的镜像注册服务器,用途:存储和分发docker镜像; 在官方的dock…

    Java 2023年6月8日
    062
  • 部署-docker安装jenkins

    什么是jenkins jenkins是基于java开发的一种持续集成的工具,提供了web界面来进行jenkins的配置与管理。jenkins通常与版本管理工具一起使用,可以实现程序…

    Java 2023年6月7日
    071
  • 使用轻量级Spring @Scheduled注解执行定时任务

    WEB项目中需要加入一个定时执行任务,可以使用Quartz来实现,由于项目就一个定时任务,所以想简单点,不用去配置那些Quartz的配置文件,所以就采用了Spring @Sched…

    Java 2023年6月7日
    070
  • Spring框架源码干货分享之三级缓存和父子工厂

    记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新。欢迎大家指正! 环境: spring5.X + idea 建议:学习过程中要开着源码一步一步过 Spri…

    Java 2023年6月5日
    080
  • Python面向对象

    1.面向对象 2.什么是类和类变量? 3.实例和实例化以及实例变量 4.数据成员 5.方法和静态方法以及类方法 6.什么是方法重写 7. _ init _ 8.self 9.类的初…

    Java 2023年6月7日
    067
  • Core Java 总结(数据类型,表达式问题)

    在jdk1.5+的环境下,如下4条语句,讨论互相==比较的输出结果 int i02=59; // 这是一个基本类型,存储在栈中。 Integer i01=59; // 调用 Int…

    Java 2023年5月29日
    0121
  • 敏捷培训有感

    一周前参加了个关于敏捷的培训,今天回想起来,记忆最深的是两个游戏环节。 游戏一 组装 10 只同样小狗,每只小狗需要 5 块积木,流水线上 5 个人,每人负责固定的一块积木的拼接。…

    Java 2023年6月16日
    067
  • dubbo源码分析6(服务暴露之本地暴露)

    前面我们做了一大堆的准备工作,包括dubbo是怎么跟spring进行整合的,然后一步一步是怎么找到启动入口的,而且还知道了,由于我们的dubbo的版本是2.7.5,所以其实启动的入…

    Java 2023年6月6日
    059
  • logback

    logback的架构 logback-core:基础模块, 为其它的两个模块提供支持logback-classic:是log4j的改进版本, 并且此模块实现了slf4j api, …

    Java 2023年6月8日
    065
  • Sentinel vs Hystrix 限流对比,到底怎么选?

    Sentinel 是阿里中间件团队开源的,面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。…

    Java 2023年5月29日
    072
  • 070_RabbitMQ的核心组成部分

    RabbitMQ的核心组成部分 RabbitMQ整体架构是什么样子的? RabbitMQ的运行流程 RabbitMQ支持消息的模式 简单模式 Simple 工作模式 Work 发布…

    Java 2023年6月7日
    091
  • Android WebView默认GONE出现的问题记录

    前段时间重构一批相似度80%以上的项目【真搞不懂前人们是怎么忍受十几个类似的应用一直CVU的,冗余代码和资源达到40%以上】 其中需要抽出一个公共的带WebView的Activit…

    Java 2023年6月9日
    059
  • 30个类手写Spring核心原理之自定义ORM(上)(6)

    本文节选自《Spring 5核心原理》 1 实现思路概述 1.1 从ResultSet说起 说到ResultSet,有Java开发经验的”小伙伴”自然最熟悉…

    Java 2023年6月7日
    079
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球