Java多线程并发写同一文件必然冲突,必须通过协调(synchronized)、隔离(分片写+合并)、缓冲(BlockingQueue+单写线程)或文件锁等方式实现安全写入,禁用多FileWriter直接append。

Java 中多个线程直接同时写同一个文件必然冲突——因为文件 I/O 是共享资源,没有协调机制时会出现数据覆盖、错乱、丢失甚至 IOException。真正可行的方案不是“让多线程自由并发写”,而是通过**协调、隔离或缓冲**来安全地完成多线程写入任务。
用 FileWriter + synchronized 控制写入入口
最简单直接的方式:把写操作封装成一个线程安全的方法,用同步块或同步方法串行化写入逻辑。适用于写入频率不高、单次内容较短的场景。
- 创建一个共享的写入工具类,内部持有一个
FileWriter(或更推荐BufferedWriter) - 所有线程调用统一的
writeLine(String line)方法,该方法用synchronized修饰或加同步块 - 注意:
FileWriter本身不线程安全,且不能多线程共用同一个实例(除非同步访问)
用 BlockingQueue + 单写线程消费(推荐)
这是高并发下最常用、最稳健的模式:多线程只负责“投递”数据,由一个专门的写线程从队列中取数据并顺序落盘。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 定义一个
BlockingQueue<string></string>(如LinkedBlockingQueue)作为缓冲区 - 各业务线程调用
queue.put(data)投递内容(可设超时避免阻塞) - 启动一个单独的守护线程,循环调用
queue.take()获取数据,并用BufferedWriter写入文件 - 优势:解耦写入逻辑,避免锁竞争;支持批量写、自动刷新、异常重试等扩展
按线程/任务分片写入,最后合并(适合离线批处理)
如果写入内容天然可分割(如每个线程处理一批记录),可让各线程写入独立临时文件,最后由主线程合并。
立即学习“Java免费学习笔记(深入)”;
- 线程 A 写
output_1.tmp,线程 B 写output_2.tmp……互不影响 - 全部完成后,用
Files.copy()或Files.write()按序追加到目标文件 - 注意:需保证最终合并顺序与业务逻辑一致(例如加序号前缀或使用 CountDownLatch 同步完成)
用 RandomAccessFile + 文件锁(慎用)
RandomAccessFile 支持定位写,配合 FileChannel.lock() 可实现区域级互斥,但实际开发中极少推荐:
- 文件锁是操作系统级的,跨 JVM 有效,但也更重、更慢
- 容易死锁(尤其锁范围没控制好)、难以调试
- NIO 锁在某些文件系统或容器环境下可能失效或行为异常
- 仅适合极特殊场景(如多进程协作写同一日志偏移位置)
FileWriter 实例同时 append = true 写同一个文件——即使设了追加模式,JVM 和 OS 无法保证 write() 调用的原子性,大概率导致内容交错或覆盖。
真正安全的并发写,本质是「减少并发」或「转移并发点」,而不是在写文件这一步硬扛竞争。

















