You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java控制台程序按下Ctrl+C时如何终止进程?

解决Ctrl+C退出控制台循环的问题

原代码里的try-catch没法处理Ctrl+C的中断——按下Ctrl+C会直接触发JVM的终止信号,不会让scanner.nextLine()抛出普通异常,所以得换个方式实现,核心是拦截中断信号+用标志位控制循环,具体如下:

解决步骤与代码

核心思路

  • 用volatile修饰布尔变量做中断标志,保证信号处理器和主线程之间的变量可见性
  • 注册信号处理器或关闭钩子,捕获Ctrl+C触发的终止信号,修改标志位
  • 把死循环改成基于标志位的循环,让程序优雅退出
  • 用try-with-resources自动管理文件流和输入流,避免资源泄漏

修改后的代码(兼容Java 8及以下)

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.Scanner;
import sun.misc.Signal;
import sun.misc.SignalHandler;

public class YourConsoleApp {
    // volatile保证多线程下变量可见性
    private static volatile boolean stopFlag = false;

    public static void concatenation(List<String> commands) throws IOException {
        // 注册SIGINT信号处理器(对应Ctrl+C)
        Signal.handle(new Signal("INT"), signal -> {
            stopFlag = true;
            System.out.println("\nInterrupted. Stopping...");
        });

        if (commands.get(1).equals(">")) {
            String path = history.getFilePath();
            File file = new File(path + "\\" + commands.get(2));
            if (file.exists() && file.isFile()) {
                // try-with-resources自动关闭writer和scanner
                try (FileWriter writer = new FileWriter(file);
                     Scanner scanner = new Scanner(System.in)) {

                    System.out.println("Write to file. Press Ctrl+C to stop.");
                    String line;
                    while (!stopFlag) {
                        if (scanner.hasNextLine()) {
                            line = scanner.nextLine();
                            writer.write(line + System.lineSeparator());
                            writer.flush();
                        }
                        // 短暂休眠减少CPU空轮询
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            stopFlag = true;
                        }
                    }
                } catch (IOException e) {
                    System.out.println("Error writing to file: " + e.getMessage());
                }
            }
        } else {
            System.out.println("bash : " + commands.get(1) + " : unrecognized operator");
        }
    }
}

Java 9+兼容方案

如果用Java 9及以上,sun.misc.Signal属于内部API可能被限制访问,可以改用JVM关闭钩子实现:

// 替换信号处理器的注册代码,改用ShutdownHook
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    stopFlag = true;
    System.out.println("\nInterrupted. Stopping...");
}));

关键说明

  1. volatile变量:stopFlag必须加volatile,因为信号处理器/关闭钩子是在独立线程中修改变量,volatile能确保主线程立刻读到最新值,不会因为线程缓存导致循环无法退出。
  2. 循环控制:把while(true)改成while(!stopFlag),当收到中断信号时,标志位变为true,循环自动终止。
  3. 资源管理:用try-with-resources包裹FileWriter和Scanner,JVM会在代码块结束时自动关闭资源,不用手动调用close()。
  4. 避免空轮询:添加Thread.sleep(100),减少循环空转对CPU的消耗。

内容的提问来源于stack exchange,提问作者Sanjay Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 13:10:48