捕捉多个Ctrl+;用Java中的C键进行优雅的强制关机

捕捉多个Ctrl+;用Java中的C键进行优雅的强制关机,java,hook,interrupt,shutdown,Java,Hook,Interrupt,Shutdown,在我的Java控制台应用程序中,我按下Ctrl+C键并添加一个线程,该线程使用Runtime.getRuntime().addShutdownHook()执行优雅的关闭 在这个线程中,我处理一些内部队列中的所有遗留工作,并优雅地退出我的应用程序,这通常是我想要的 但是,有时应用程序可能会有需要一段时间(几分钟)才能处理的内部队列,如果是这样,我希望有一个选项,可以再次按Ctrl+C以强制退出应用程序 我见过其他应用程序以这种方式工作,但我不知道如何在Java中捕获第二个Ctrl+C?警告,这不是

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

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

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


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

警告,这不是您应该做的。为避免阳光照射,请使用包装。在实际代码中使用它之前,请三思而后行。至少,信号处理的访问应通过反射完成,并在故障时返回到记录通常的停机挂钩。为了简洁起见,我把它省略了

所以,你们这些进入这里的人,一切希望都放弃了:

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();
            }
        }
    }
}
import java.util.concurrent.AtomicBoolean;
导入sun.misc.Signal;
导入sun.misc.SignalHandler;
公共类信号{
私有静态void prepareShutdownHandling(){
//这将是正常的关机挂钩
最终线程关闭=新线程(){
@凌驾
公开募捐{
//模拟慢速关机
对于(int i=0;i<10;i++){
System.out.println(“正常关机运行”);
试一试{
睡眠(1000);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
System.out.println(“正常关机完成”);
系统出口(0);
}
};
handle(新信号(“INT”),新信号处理器(){
私有AtomicBoolean inShutdown=新的AtomicBoolean();
公共无效手柄(信号信号){
if(inshutton.compareAndSet(false,true)){
//正常关机
shutdown.start();
}否则{
系统错误println(“紧急停机”);
系统出口(1);
}
}
});
}
公共静态void main(字符串参数[]){
prepareShutdownHandling();
while(true){
System.out.println(“主程序运行”);
试一试{
睡眠(1000);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
}

感谢您提供的优雅解决方案!因此,本质上,它归结为不可能使用Java以可移植/跨平台的方式进行所需的信号处理?(不使用sun.*库)或者如果信号处理在不同平台之间变化很大,可能真的是在任何语言中?@Nils我很难称之为优雅:-d.AFAIK没有可移植的方式,支持的非可移植方式(信号链)在通常的信号处理之后运行处理程序,所以我认为它不会工作(我没有尝试)。但是也许有人想出了一个更可靠的破解方法。看起来没有sun也可以这么做。*是:默认的SIGINT处理程序可以用-Xrs参数来抑制。然后,信号处理可以在本机代码中完成。对于该解决方案的可移植性也不是很好——无论是命令行开关还是本机代码。