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

如何避免Java命令行输入被线程打印操作中断?

解决Java线程输入被打印打断的问题

方案1:使用ANSI转义序列控制光标位置

大部分现代终端支持ANSI转义码,通过保存和恢复光标位置,让线程B的打印不会干扰输入光标。

修改线程B的代码:

@Override
public void run() {
    while (true) {
        // 保存当前光标位置
        System.out.print("\033[s");
        // 打印内容到新行
        System.out.println("test");
        // 恢复光标到之前输入的位置
        System.out.print("\033[u");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            break;
        }
    }
}

原理:\033[s指令会记录当前光标坐标,\033[u会把光标移回记录的位置。这样线程B打印后,光标自动回到输入的地方,输入内容不会被打断。

方案2:用JCurses分离输入输出区域

JCurses是Java的终端UI库,可以将终端划分为独立的输入区和输出区,彻底避免两者干扰。

示例代码:

import curses.Curses;
import curses.Window;

public class ConsoleApp {
    public static void main(String[] args) throws Exception {
        // 初始化JCurses
        Curses.init();
        Window mainWindow = Curses.getWindow();
        int totalHeight = mainWindow.getHeight();

        // 输出区:占据终端前totalHeight-1行
        Window outputWindow = mainWindow.subWindow(totalHeight - 1, mainWindow.getWidth(), 0, 0);
        // 输入区:占据终端最后一行
        Window inputWindow = mainWindow.subWindow(1, mainWindow.getWidth(), totalHeight - 1, 0);

        // 启动打印线程
        new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                outputWindow.addLine("test");
                outputWindow.refresh();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }).start();

        // 监听输入
        inputWindow.setCursorVisible(true);
        while (true) {
            String command = inputWindow.readLine();
            // 处理输入的命令,比如输出到输出区
            outputWindow.addLine("收到命令:" + command);
            outputWindow.refresh();
        }
    }
}

注意:需要先引入JCurses的依赖包,这种方式适合需要复杂终端交互的场景。

方案3:同步控制台输出锁

通过全局锁让打印操作和输入操作互斥,确保输入时不会有内容插入。

示例代码:

import java.util.Scanner;

public class SyncConsole {
    private static final Object CONSOLE_LOCK = new Object();

    public static void main(String[] args) {
        // 打印线程
        new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                synchronized (CONSOLE_LOCK) {
                    System.out.println("test");
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }).start();

        // 输入线程(主线程)
        Scanner scanner = new Scanner(System.in);
        while (true) {
            synchronized (CONSOLE_LOCK) {
                System.out.print("> ");
            }
            String command = scanner.nextLine();
            synchronized (CONSOLE_LOCK) {
                System.out.println("执行命令:" + command);
            }
        }
    }
}

原理:线程B只有在主线程未处于输入等待状态时才能获取锁打印,输入过程中打印会被阻塞,直到输入完成。缺点是打印可能会有延迟,但输入体验不受影响。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 04:45:35