最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Java多线程编程:StringBuffer为何慢于StringBuilder
时间:2026-06-23 08:38:52 编辑:袖梨 来源:一聚教程网
StringBuffer因所有公开方法加synchronized而比StringBuilder慢2–4倍,核心差异仅在于同步关键字,二者底层实现完全相同;线程安全仅在多线程共享同一实例时必要,局部使用应选StringBuilder,并预设容量以减少扩容开销。
因为 StringBuffer 的每个公开方法都加了 synchronized,而 StringBuilder 完全不加锁——同步机制本身就会带来锁获取、释放、内存屏障等开销,哪怕只有一个线程在跑,也绕不开。
核心差异就在一个关键字上
StringBuffer 和 StringBuilder 底层共享同一套实现(都继承自 AbstractStringBuilder),用的都是可变的 char[](JDK9+ 改为 byte[]),扩容逻辑、append 行为、内部缓冲管理全都一样。唯一的区别是:StringBuffer 的 append()、toString()、delete() 等所有公共方法签名上都明确写了 synchronized;StringBuilder 则完全没这层修饰。
这意味着:
- 每次调用 StringBuffer 方法,JVM 都必须执行锁的进入与退出流程
- 即使当前线程是唯一使用者,也要承担锁的内存可见性保障成本
- JVM 对 synchronized 块会做更保守的优化,比如限制指令重排范围
性能差距不是“略慢”,而是实打实的开销
在单线程下做 10 万次 append("x"):
立即学习“Java免费学习笔记(深入)”;
- StringBuilder 通常耗时约 8–12ms
- StringBuffer 往往需要 28–45ms,慢了约 2–4 倍
这个差距不来自算法或数据结构,纯粹来自同步带来的额外字节码指令和运行时机制。锁竞争越少,相对差距越稳定;但只要加了 synchronized,就不可能比无锁版本快。
线程安全不是默认选项,而是明确需求
StringBuffer 的线程安全是有代价的,但它只在一种场景下真正必要:
- 多个线程**同时读写同一个 StringBuffer 实例**(例如作为 static 全局变量、被注入到 Spring 单例 Bean 中并跨请求复用)
- 且你无法重构为线程局部使用(如 ThreadLocal<StringBuilder>)或不可变结果传递
如果只是方法内局部创建、拼完即弃,或者通过 ThreadLocal 隔离,用 StringBuffer 就等于主动给单线程任务加锁——白耗资源,还掩盖真实并发风险。
别忽略容量预设这个小优化
无论选哪个,如果能预估最终长度,初始化时指定容量能减少数组复制次数:
- new StringBuilder(1024) 比 new StringBuilder()(默认 16)更适合拼接长文本
- 扩容公式是 新容量 = 旧容量 × 2 + 2,频繁扩容会触发多次 System.arraycopy
这点对两者都适用,但对 StringBuilder 更值得做——它本就轻量,省下的复制开销更直接体现为性能提升。
相关文章
- steam上传视频教程 06-23
- 布袋鼠小说app如何进行阅读 06-23
- 快手极速版官方App网页版在哪下载 06-23
- 我的世界2026秒玩入口网址是什么 06-23
- 空洞骑士丝之歌全部五个结局攻略 丝之歌结局达成条件 06-23
- 崩坏3 8.7新春版本福利一览 06-23