当前位置: 首页 > 知识库问答 >
问题:

捕获Java中的多个Ctrl C键,以实现优雅的强制关机

蓬弘
2023-03-14

在我的Java控制台应用程序中,我按下Ctrl C键并添加一个线程,使用Runtime.getRuntime(). addShutdownHook()执行优雅的关机

在这个线程中,我处理一些内部队列中的所有遗留工作,并优雅地退出我的应用程序,这通常是我想要的。

然而,有时应用程序可能会有需要一段时间(几分钟)才能处理的内部队列,如果是这样的话,我希望有一个选项可以再次按Ctrl C以强制退出应用程序。

我见过其他应用程序以这种方式工作,但我不知道如何在Java中捕获第二个Ctrl C?

共有2个答案

谭宏盛
2023-03-14

使用信号。SIGINT上的句柄,并在处理程序中还原原始默认的SIG\U DFL处理程序。因此,如果再次命中,它将使用SIG\U DFL处理程序(由操作系统提供)终止程序。

private void registerSigIntHandler() {
    Signal.handle(new Signal("INT"), new SignalHandler() {
        public void handle(Signal sig) {
            log.info("SIGINT received");
            Signal.handle(new Signal("INT"), SignalHandler.SIG_DFL);
            shutdown();
            SignalHandler.SIG_DFL.handle(new Signal("INT"));
        }
    });
}

一旦关闭方法完成,这还会调用SIG\u DFL处理程序来终止进程。

https://stackoverflow.com/a/71028985/854342

章翔宇
2023-03-14

警告,这不是你应该做的。避免使用sun软件包的常见原因适用。在实际的代码中使用它之前要三思而后行。信号处理的访问至少应通过反射完成,并在故障时返回到记录通常的停机挂钩。为了简洁起见,我省略了这一点。

所以,进入这里的人,放弃所有的希望:

import java.util.concurrent.atomic.AtomicBoolean;
import sun.misc.Signal;
import sun.misc.SignalHandler;

public class Sigint {
    private static void prepareShutdownHandling() {
        // This would be the normal shutdown hook
        final Thread shutdown = new Thread() {
            @Override
            public void run() {
                // Simulate slow shutdown
                for (int i = 0; i < 10; i++) {
                    System.out.println("Normal shutdown running");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("Normal shutdown finished");
                System.exit(0);
            }
        };

        Signal.handle(new Signal("INT"), new SignalHandler() {
            private AtomicBoolean inShutdown = new AtomicBoolean();
            public void handle(Signal sig) {
                if (inShutdown.compareAndSet(false, true)) {
                    // Normal shutdown
                    shutdown.start();
                } else {
                    System.err.println("Emergency shutdown");
                    System.exit(1);
                }
            }
        });
    }

    public static void main(String args[]) {
        prepareShutdownHandling();
        while (true) {
            System.out.println("Main program running");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
 类似资料:
  • 问题内容: 谁能告诉我为什么这个类的输出是’xa’? 为什么不会捕获其他异常(RuntimeException和Exception)? 问题答案: 抛出的唯一异常是throw语句旁边的那个异常。另一个已创建但未抛出。无法同时引发两个异常。 通常,当在另一个异常的构造函数中传递异常时,将指示该异常是导致此异常的原因。但是,实际抛出的唯一异常是throw语句旁边的异常。 在这种情况下,NullPoin

  • 问题内容: 如何在多进程python程序中捕获+ ,并正常退出所有进程,我需要在Unix和Windows上均可使用的解决方案。我尝试了以下方法: 这是可行的,但我认为这不是正确的解决方案。 问题答案: 正确的方法来处理/用是: 在创建流程之前,请忽略该流程。这样创建的子进程继承了处理程序。 创建a之后,在父进程中还原原始处理程序。 使用和代替阻塞和。 等待结果超时,因为默认阻塞将等待忽略所有信号。

  • 优雅关闭,包括两部分,一个是 RPC 框架作为客户端,一个是 RPC 框架作为服务端。 作为服务端 作为服务端的时候,RPC 框架在关闭时,不应该直接暴力关闭。在 RPC 框架中 com.alipay.sofa.rpc.context.RpcRuntimeContext 在静态初始化块中,添加了一个 ShutdownHook // 增加jvm关闭事件 if (RpcConf

  • 我用的是spring kafka 1.2.2。释放目前,我已经为没有BackOffPolicy和AlwaysRetryPolicy的容器配置了重试模板。确认模式为手动或立即。 当一个SIGTERM出现时,我会让当前消息被处理,当@KafkaListener再次被调用时,我会在容器上抛出RuntimeException,该容器会无限期重试并持续抛出异常。一段时间后,SIGKILL被发出,容器被停止(

  • 如果我们在后台启动KafkaStream应用程序(比如Linux),有没有一种方法可以从外部向应用程序发出信号,从而启动优雅的关机?

  • Java7编译器是如何处理多捕获块的?一个简单的实现是生成字节码,就好像存在多个catch块一样。然而,我从多个来源得到的信息表明,情况并非如此--处理多个异常类型的catch块在编译期间不会产生重复的字节码。 那么,它是如何工作的呢?是否有一个新的字节码指令告诉JVM关于多捕获块?