BufferedWriter非线程安全,多线程共用会导致数据错乱、覆盖或重叠;因其内部缓冲区和游标被并发修改,如多线程同时写入同一位置或并发flush引发重复刷出或漏刷。

BufferedWriter 本身不是线程安全的,多线程直接共用同一个实例写入文件,必然导致数据错乱、覆盖或重叠——这不是 bug,而是设计使然。
为什么 BufferedWriter 会数据重叠?
BufferedWriter 内部维护一个字符缓冲区(char[])和一个游标(count),多个线程同时调用 write() 或 flush() 时,可能同时修改游标位置或缓冲区内容。例如:线程 A 写到位置 5,线程 B 也写到位置 5,结果后者覆盖前者;或者 flush() 被多个线程并发触发,造成部分缓冲区重复刷出或漏刷。
常见错误写法
- 多个线程共享一个 FileWriter + BufferedWriter 实例(如 static 字段或单例注入)
- 虽为每个线程 new 了 BufferedWriter,但底层 FileWriter 指向同一文件且未加同步(FileWriter 默认以 append=false 打开,会截断重写)
- 用 synchronized 包裹 write() 但忘了 flush() 或 close() 的并发风险,或同步粒度太粗影响性能
安全的解决方案
根据场景选择合适方式:
- 写入不同文件:每个线程独占一个 BufferedWriter(new FileWriter(file, true) + new BufferedWriter(...)),append=true 避免覆盖
-
写入同一文件且顺序不敏感:用
java.nio.channels.FileChannel配合ByteBuffer和position()显式控制偏移,或用RandomAccessFile定位写入(需自行处理换行与编码) - 写入同一文件且需保序/原子追加:用单个专用写线程(如 BlockingQueue + Consumer 线程),其他线程只投递日志/记录对象,由该线程串行写入
- 轻量级日志类场景:考虑 Log4j2 / SLF4J + Logback,它们内置异步 Appender 和线程安全的 I/O 封装
快速验证是否线程安全问题
写个最小复现:启动 10 个线程,每线程 write("T"+i+": hello\n") 100 次,观察文件行数是否为 1000、每行是否完整、有无“T3: helloT4: hello”这类粘连。若出现,基本可确认是并发写冲突。
立即学习“Java免费学习笔记(深入)”;


















