千家信息网

Java优雅停机的实现及原理是什么

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章给大家介绍Java优雅停机的实现及原理是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。优雅停机? 这个名词我是服的,如果抛开专业不谈,多好的名词啊!其实优雅停机,就是
千家信息网最后更新 2026年11月02日Java优雅停机的实现及原理是什么

这篇文章给大家介绍Java优雅停机的实现及原理是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

优雅停机? 这个名词我是服的,如果抛开专业不谈,多好的名词啊!

其实优雅停机,就是在要关闭服务之前,不是立马全部关停,而是做好一些善后操作,比如:关闭线程、释放连接资源等。

再比如,就是不会让调用方的请求处理了一增,一下就中断了。而处理完本次后,再停止服务。

Java语言中,我们可以通过Runtime.getRuntime().addShutdownHook()方法来注册钩子,以保证程序平滑退出。(其他语言也类似)

来个栗子:

public class ShutdownGraceFullTest {      /**      * 使用线程池处理任务      */     public static ExecutorService executorService = Executors.newCachedThreadPool();      public static void main(String[] args) {          //假设有5个线程需要执行任务         for(int i = 0; i < 5; i++){             final int id = i;             Thread taski = new Thread(new Runnable() {                 @Override                 public void run() {                     System.out.println(System.currentTimeMillis() + " : thread_" + id + " start...");                     try {                         TimeUnit.SECONDS.sleep(id);                     } catch (InterruptedException e) {                         e.printStackTrace();                     }                     System.out.println(System.currentTimeMillis() + " : thread_" + id + " finish!");                 }             });             taski.setDaemon(true);             executorService.submit(taski);         }          // 添加一个钩子处理未完任务         Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {             @Override             public void run() {                  System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " No1 shutdown hooking...");                 boolean shutdown = true;                 try {                     executorService.shutdown();                     System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() +  " shutdown signal got, wait threadPool finish.");                     executorService.awaitTermination(1500, TimeUnit.SECONDS);                     System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() +  " all thread's done.");                 }                 catch (InterruptedException e) {                     e.printStackTrace();                 }                 System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " No1 shutdown done...");             }         }));          // 多个关闭钩子并发执行         Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {             @Override             public void run() {                 try {                     System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " No2 shutdown hooking...");                     Thread.sleep(1000);                 } catch (InterruptedException e) {                     e.printStackTrace();                 }                 System.out.println(System.currentTimeMillis() + " : " + Thread.currentThread().getName() + " No2 shutdown done...");             }         }));          System.out.println("main method exit...");         // 故意调用jvm退出命令,发送关闭信号,否则正常情况下 jvm 会等待***一个非守护线程关闭才会退出         System.exit(0);     } }

运行结果如下:

很明显,确实是优雅了,虽然***收到了一关闭信号,但是仍然保证了任务的处理完成。很棒吧!

那么,在实际应用中是如何体现优雅停机呢?

kill -15 pid

通过该命令发送一个关闭信号给到jvm, 然后就开始执行 Shutdown Hook 了,你可以做很多:

  1. 关闭 socket 链接

  2. 清理临时文件

  3. 发送消息通知给订阅方,告知自己下线

  4. 将自己将要被销毁的消息通知给子进程

  5. 各种资源的释放

而在平时工作中,我们不乏看到很多运维同学,是这么干的:

kill -9 pid

如果这么干的话,jvm也无法了,kill -9 相当于一次系统宕机,系统断电。这会给应用杀了个措手不及,没有留给应用任何反应的机会。

所以,无论如何是优雅不起来了。

要优雅,是代码

其中,线程池的关闭方式为:

executorService.shutdown();  executorService.awaitTermination(1500, TimeUnit.SECONDS);

ThreadPoolExecutor 在 shutdown 之后会变成 SHUTDOWN 状态,无法接受新的任务,随后等待正在执行的任务执行完成。意味着,shutdown 只是发出一个命令,至于有没有关闭还是得看线程自己。

ThreadPoolExecutor 对于 shutdownNow 的处理则不太一样,方法执行之后变成 STOP 状态,并对执行中的线程调用 Thread.interrupt() 方法(但如果线程未处理中断,则不会有任何事发生),所以并不代表"立刻关闭"。

shutdown() :启动顺序关闭,其中执行先前提交的任务,但不接受新任务。如果已经关闭,则调用没有附加效果。此方法不等待先前提交的任务完成执行。

shutdownNow():尝试停止所有正在执行的任务,停止等待任务的处理,并返回正在等待执行的任务的列表。当从此方法返回时,这些任务将从任务队列中耗尽(删除)。此方法不等待主动执行的任务终止。

executor.awaitTermination(this.awaitTerminationSeconds, TimeUnit.SECONDS)); 控制等待的时间,防止任务***期的运行(前面已经强调过了,即使是 shutdownNow 也不能保证线程一定停止运行)。

注意:

  • 虚拟机会对多个shutdownhook以未知的顺序调用,都执行完后再退出。

  • 如果接收到 kill -15 pid 命令时,执行阻塞操作,可以做到等待任务执行完成之后再关闭 JVM。同时,也解释了一些应用执行 kill -15 pid 无法退出的问题,如:中断被阻塞了,或者hook运行了死循环代码。

关于Java优雅停机的实现及原理是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

任务 线程 优雅 处理 命令 方法 应用 运行 信号 正在 钩子 保证 原理 代码 内容 名词 多个 就是 更多 机会 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网黑科技 广州大一互联网络科技有限公司 湖南永感互联网科技有限公司 科技赋能下的互联网金融 互联网中国科技 唐信互联网科技 大连 互联网科技公司名称 互联网科技公司的市场部门 科技与互联网的利与弊 宝灵互联网科技有限公司 晓花互联网科技有限公司网址 江阴互联网智能科技产品进口 内蒙古九一互联网科技 互联网科技包装股份有限公司上市 神州科技互联网有限公司 湖北辰鑫科技互联网 银川新华互联网科技学校原画 悟空问答互联网科技 承德科技产业互联网平台 中国主要互联网科技公司 南京欣网互联网络科技 港股互联网科技股 易互联网科技有限公司 互联网科技英文 互联网高科技股票 山东吉时兔互联网科技有限公司 互联网科技公司的市场部门 西藏七维空间互联网科技有限公司 元气玛特互联网科技公司是外包吗 深圳互联网科技的发展
0