必须同步控制多线程对filewriter的并发写入,否则导致内容交叉、覆盖、丢失;推荐用synchronized块、reentrantlock、复用线程安全写入器或队列+单写线程四种方案。

核心就一条:不能让多个线程直接并发调用 FileWriter 实例的写操作,必须加同步控制。否则操作系统调度不可控,缓冲区、文件指针、追加位置全乱套,内容必然交叉、覆盖、丢失。
用 synchronized 锁住共享资源
最直接有效的方式是把写入逻辑包进同步块或同步方法,锁对象推荐用同一个 File 实例或专用锁对象(避免锁 this 引发意外竞争):
- 每次写前获取锁,写完立即释放,确保同一时刻只有一个线程在执行
write()和flush() - 注意:
FileWriter本身不是线程安全的,即使开了追加模式(true),也不能靠它解决并发问题 - 示例中别用
new FileWriter(file, true)每次都新建——频繁开闭句柄易失败,且锁不住实际 I/O 行为
用 ReentrantLock 显式控制时序
比 synchronized 更灵活,支持超时、可中断、公平性等,适合复杂场景:
- 声明一个
static final ReentrantLock lock = new ReentrantLock(),所有线程共用 - 写操作前调用
lock.lock(),务必在finally块中lock.unlock() - 配合
BufferedWriter提升效率,但记得手动flush()或启用自动 flush(如用PrintWriter)
复用单个线程安全的写入器(推荐用于日志类场景)
不反复创建流,而是初始化一次、长期持有,再用同步保障调用安全:
- 例如:用
PrintWriter包一层BufferedWriter(new FileWriter("log.txt", true)),设为autoFlush = true - 把这个
PrintWriter设为static或单例成员,所有线程都通过它写 - 对外写方法加上
synchronized,或用锁保护其println()调用 - 务必定期检查
checkError(),因为PrintWriter出错不抛异常,静默失败很隐蔽
避开共享写入:改用队列+单写线程
彻底消除多线程直接碰文件的可能,适合高吞吐、强一致性要求的场景:
- 所有线程把待写内容发到一个线程安全队列(如
BlockingQueue) - 单独起一个守护线程,持续从队列取数据、批量写入文件
- 这个写线程自己管理
FileWriter生命周期,无需任何锁,天然串行 - 还能顺便做合并、压缩、滚动、异步落盘等增强功能
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











