如何避免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
相关产品推荐
相关产品推荐

