StringBuffer 能用于多线程是因为其所有修改方法(如 append、insert 等)均被 synchronized 修饰,确保同一时刻仅一个线程执行,从而保障共享实例的数据一致性与操作原子性。

StringBuffer 本身是线程安全的,适合多线程环境下的字符串拼接,但实际开发中通常不推荐直接用于高并发拼接场景。它的线程安全性靠方法级 synchronized 实现,会带来明显性能开销;若无共享实例或明确需要同步保障,反而可能成为瓶颈。
为什么 StringBuffer 能用于多线程?
StringBuffer 的所有修改方法(如 append()、insert()、delete()、reverse())都被声明为 synchronized,确保同一时刻只有一个线程能执行这些操作。这意味着:
- 多个线程共用同一个 StringBuffer 实例时,不会出现数据错乱或部分写入问题
- 无需额外加锁,调用方不用关心同步逻辑
- 底层字符数组(value)的修改始终在临界区内完成
典型多线程使用方式(需注意共享范围)
若确实需要跨线程协作构建一个字符串(例如日志聚合、批量结果收集),可按如下方式安全使用:
- 将 StringBuffer 实例作为共享对象(如通过构造函数传入、静态字段或线程间传递)
- 各线程只调用其线程安全的方法(避免手动操作内部 value 数组)
- 最终由某一线程调用 toString() 获取结果(该方法不修改状态,无需同步)
示例:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
立即学习“Java免费学习笔记(深入)”;
StringBuffer sharedBuf = new StringBuffer();
ExecutorService pool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
pool.submit(() -> sharedBuf.append("item-").append(Thread.currentThread().getId()).append(";"));
}
pool.shutdown();
pool.awaitTermination(5, TimeUnit.SECONDS);
System.out.println(sharedBuf.toString()); // 如 "item-11;item-12;item-13;"(顺序不定但内容完整)
更优替代方案(多数情况下建议)
除非必须复用同一实例并强依赖内置同步,否则优先考虑以下方式:
- 每个线程用 StringBuilder 独立拼接,最后合并:避免锁竞争,性能更高
- 使用线程安全容器收集结果(如 CopyOnWriteArrayList<String>),再用 String.join() 或 Collectors.joining()
- 高并发日志类场景可考虑无锁队列(如 Disruptor)+ 异步刷写,而非在拼接阶段同步
- Java 8+ 推荐用 Stream + parallelStream() 配合 Collectors.joining(),语义清晰且由框架处理并发
关键提醒
StringBuffer 不是“万能多线程字符串工具”:
- 它只保证单个方法调用的原子性,不保证多个方法组合操作的原子性(如先 append 再 length() 判断,中间可能被其他线程修改)
- 若需复合逻辑(如“只有长度小于100才追加”),仍需外部同步
- 频繁扩容(ensureCapacity)也会被同步,高并发下易成热点
- 现代 JVM 对 StringBuilder 的 JIT 优化更好,单线程性能远超 StringBuffer

















