Java控制台聊天室通过多线程实现:每个用户独立线程负责输入监听、消息收发;服务端用CopyOnWriteArrayList和ConcurrentLinkedQueue保障线程安全;消息采用文本协议如[user] msg;支持JOIN/QUIT指令与ANSI着色;退出时volatile标志+interrupt优雅终止。

用Java写一个控制台版聊天室,核心是让多个用户(线程)能同时收发消息,共享同一套聊天记录和在线用户列表。关键不在于界面多炫,而在于线程安全、通信逻辑清晰、资源不冲突。
多线程分工:每个客户端一个线程
模拟多个用户登录,就为每个用户启动一个独立线程(比如用Thread或ExecutorService)。该线程负责:监听本用户的键盘输入、把消息发给服务器、接收并打印其他人的消息。注意别让所有线程共用同一个Scanner实例,否则输入会互相抢占。
- 建议为每个客户端线程创建专属的Scanner(System.in),但更稳妥的做法是只让主线程读输入,再分发到各客户端——避免System.in竞争
- 客户端线程用while(true)循环持续检查是否有新消息可读(可用阻塞队列或简单的同步List+wait/notify)
服务端统一管理:用线程安全容器存用户和消息
服务端用一个单独线程(或主线程)运行,维护两个关键共享资源:在线用户列表、聊天历史。这两者会被多个客户端线程并发读写,必须保证线程安全。
- 用户列表用CopyOnWriteArrayList或Collections.synchronizedList(new ArrayList())
- 聊天消息可用ConcurrentLinkedQueue存放,或加锁的ArrayList配合synchronized块
- 每次有新消息,服务端广播给所有在线用户线程(遍历用户列表,调用其发送方法)
消息格式与简单协议
不用复杂序列化,用纯文本约定即可。例如:[userA] Hello world! 或 JOIN:userB、QUIT:userC。客户端线程解析前缀判断是普通消息、上线通知还是下线提示。
立即学习“Java免费学习笔记(深入)”;
- 服务端收到输入后,先识别指令(如/quit),再决定是广播消息、移除用户,还是存入聊天记录
- 客户端线程在打印前可对消息做简单着色(用ANSI转义码,如\u001B[32m绿色用户名),提升可读性
退出机制与资源清理
用户输入/exit或/quit时,不仅要从用户列表中移除自己,还要中断对应线程的监听循环,并关闭其相关流(如有)。主线程检测到所有客户端退出后,再优雅关闭服务端。
- 用volatile boolean running标志位控制客户端线程循环,避免死循环
- 使用Thread.interrupt()配合InterruptedException处理,确保线程能及时响应退出请求
- 最后调用System.exit(0)前,确认所有线程已终止(可用thread.isAlive()检查)










