选 StringBuilder 还是 StringBuffer 取决于线程环境:单线程用 StringBuilder,多线程共享修改用 StringBuffer;两者底层实现相同,均基于可变数组、自动扩容、API 兼容,唯一区别是 StringBuffer 方法加 synchronized 保证线程安全,StringBuilder 无同步开销,性能高 10%–15%。

选 StringBuilder 还是 StringBuffer,关键看线程环境——单线程用 StringBuilder,多线程且需共享修改用 StringBuffer。
底层实现其实一样
两者都继承自 AbstractStringBuilder,内部都用可变的 char[](JDK 9+ 为 byte[])存字符,都支持 append、insert、delete 等原地修改操作,扩容逻辑也一致:容量不够时自动扩容(通常是当前长度 ×2 +2),调用 System.arraycopy 复制内容。
它们的 API 几乎完全兼容,方法签名、参数类型、返回值都一致,代码迁移成本极低。
线程安全是唯一本质区别
StringBuffer 的所有公共修改方法(如 append、insert、reverse)都加了 synchronized,保证多线程并发调用时数据不会错乱;StringBuilder 完全不加锁,没有任何同步开销。
立即学习“Java免费学习笔记(深入)”;
- 在纯单线程场景下,StringBuilder 性能通常比 StringBuffer 高 10%–15%
- 如果多个线程共用同一个 StringBuffer 实例并频繁修改,不用额外同步也能安全运行
- 但若用 StringBuilder 做同样操作,大概率出现字符错位、丢失或数组越界异常
初始化容量影响实际性能
默认构造器创建的 StringBuilder/StringBuffer 初始容量都是 16。如果预估最终字符串长度远超此值(比如拼接上千条日志),建议直接指定初始容量:
-
new StringBuilder(2048)可避免多次扩容复制 - 扩容虽自动,但每次都要 new 数组 + copy 原内容,属于可避免的开销
- 过度预留(如设为 100000)会浪费堆内存,按需略留余量更合理
别混淆“线程安全”和“线程可用”
线程安全 ≠ 必须多线程用;线程不安全 ≠ 单线程不能用。
- 局部变量(如方法内新建的 StringBuilder)天然线程隔离,用 StringBuilder 安全又高效
- 静态字段或全局共享实例,若被多线程读写,必须选 StringBuffer 或自行加锁
- 仅读操作(如 toString() 后只读取结果)对两者都没影响,无需担心


















