控制台聊天模拟程序需用多线程分离输入与输出以避免阻塞假死,推荐输入线程用Scanner(System.in, "UTF-8")读取,输出线程用volatile标志位控制定时回复,并通过ConcurrentLinkedQueue传递消息,同时注意Windows下cmd编码需设为UTF-8。

控制台聊天模拟程序不需要网络通信,核心是多线程协调输入与输出,避免阻塞导致“卡死”
用 Scanner 读取用户输入时必须注意阻塞问题
控制台输入本质是阻塞式操作,Scanner.nextLine() 会一直等回车。如果把它放在主线程里,而另一方(比如模拟的“对方”)也依赖主线程输出,就会互相等待、假死。
- 不要把输入和输出逻辑都塞进同一个循环或同一个线程
- 推荐拆成两个独立线程:一个专管
System.in输入,另一个负责定时/事件驱动的输出(比如模拟对方回复) - 若仅做单机双角色模拟(如 A 和 B 轮流说话),可用
while+Scanner+ 状态标记,但需明确约定输入格式(例如以/quit退出)
用 Thread 模拟“对方回复”要避免忙等待
直接写 while(true) { Thread.sleep(1000); System.out.println("B: ..."); } 看似简单,但容易和用户输入冲突,且无法响应中断。
- 给模拟回复线程设置标志位(如
volatile boolean running = true),在用户输入/quit后设为false安全退出 - 用
Thread.sleep()代替空循环,减少 CPU 占用 - 若想让“对方”更智能(比如根据输入关键词回复),可在输入线程中把消息存入
Queue,回复线程从中取值处理——注意加同步或用ConcurrentLinkedQueue
中文乱码常见于 Windows 控制台默认编码
在 IntelliJ 或 Eclipse 运行正常,但 cmd 中运行出现问号或方块,大概率是编码不匹配。
立即学习“Java免费学习笔记(深入)”;
- Java 源文件保存为 UTF-8,但 Windows
cmd默认是 GBK,Scanner会按平台默认编码读取 - 显式指定输入编码:
new Scanner(System.in, "UTF-8")(前提是终端已用chcp 65001切换到 UTF-8) - 更稳妥做法:统一用
InputStreamReader+BufferedReader,并传入StandardCharsets.UTF_8
真正难的不是写完能“一问一答”,而是让两个角色看起来在“同时”说话、不抢光标、不丢消息、能随时退出——这些细节全藏在线程协作和 I/O 缓冲控制里。










