




StringBuffer 线程安全而 StringBuilder 不安全,因前者所有公共方法加 synchronized,后者无同步;单线程下 StringBuilder 快 15%–25%,且 toString() 缓存优化实际无效。
关键就一点:StringBuffer 的所有公共方法(如 append、insert、delete)都加了 synchronized,而 StringBuilder 完全没加。这意味着:
StringBuffer 实例的 append,不会出现数据错乱; StringBuilder,极大概率产生脏数据(比如字符串拼接缺字、顺序混乱),且这种 bug 很难复现和调试。这不是“理论风险”,而是 JVM 内存模型决定的:字符数组 value[] 的读写不满足原子性,没有同步机制时,一个线程看到的可能是另一个线程只写了一半的状态。
不是“慢一点”,而是有可测量的开销:
synchronized 方法,JVM 都要检查锁状态(偏向锁 → 轻量级锁 → 可能升级为重量级锁); 
append 操作,StringBuilder 比 StringBuffer 快约 15%–25%,差距随操作复杂度增大。所以别信“反正就我一个线程,用哪个都行”——只要没明确需要线程安全,StringBuffer 就是多花了钱还买了个锁。
真实项目中极少,但必须用的典型情况只有:
StringBuffer); 注意:Spring、Logback、Jackson 等主流框架内部早已全部切换为 StringBuilder;如果你在写新代码还选 StringBuffer,大概率只是因为 IDE 自动补全弹出了它。
StringBuffer 内部有个 toStringCache 字段,用于缓存上一次 toString() 的结果;每次 append 前都会把它置为 null。而 StringBuilder 没这层逻辑,每次 toString() 都直接调用 Arrays.copyOfRange(value, 0, count)。
这意味着:
toString() 且中间不做修改,StringBuffer 有微弱优势; toString(),这个优化形同虚设; toStringCache 本身也是个对象引用,GC 压力略高,反而可能抵消那点好处。真正该关心的,是别在循环里反复新建 StringBuffer 或 StringBuilder 实例——初始化容量(比如 new StringBuilder(1024))比纠结用哪个类影响大得多。