stringbuffer是线程安全的字符串缓冲区,所有修改方法加synchronized锁保障数据一致性但牺牲性能;适合多线程共享写入场景,不适合高频并发拼接;优化需合理初始化容量、避免重复加锁,替代方案包括threadlocal、不可变聚合等。

StringBuffer在多线程环境下不是“更快”的选择,而是“更稳”的选择——它不提升性能,但能防止数据错乱。
StringBuffer真正的价值是线程安全,不是高性能
它的所有修改方法(append、insert、delete等)都加了synchronized锁,意味着同一时间只有一个线程能执行操作。这带来确定性结果,但也会引发锁竞争、线程阻塞和上下文切换开销。实测显示:4线程并发拼接各10万次时,StringBuffer耗时比单线程StringBuilder高约2.8倍,且吞吐量随线程数增加明显下降。
- 适合场景:多个线程往同一个缓冲区写日志、拼接配置参数、收集响应内容
- 不适合场景:高频、细粒度的并发拼接(如每毫秒上百次append)
- 关键事实:它不会丢字符、不会越界、不会抛ArrayIndexOutOfBoundsException,而StringBuilder在共享使用时大概率会
用对StringBuffer的关键细节
光用StringBuffer还不够,得避开常见坑:
- 初始化时设合理容量(如new StringBuffer(1024)),减少扩容时的锁争抢
- 避免在synchronized方法外再套synchronized块,重复加锁徒增开销
- 不要把它当“万能并发工具”——如果只是线程间传递拼接结果,优先用ThreadLocal
- 若只需最终合并结果,让每个线程用独立StringBuilder,最后用StringBuffer或+拼接汇总
比StringBuffer更优的替代思路
高并发下硬扛锁不是好办法,设计上解耦更有效:
- 用ThreadLocal
:每个线程独享实例,无锁、复用、零干扰 - 改用不可变聚合:各线程生成字符串片段,用List
收集,最后用String.join()合并 - 极少量共享更新场景:用AtomicReference
配合CAS替换,或ConcurrentLinkedQueue暂存待拼内容 - 日志类场景可直接用Log4j2/SLF4J的异步Appender,底层已做线程隔离
StringBuffer的作用很明确:当你确实需要多个线程共写一个可变字符串,且不能接受结果错误时,它是少数几个能兜底的选项之一。但它不是性能解法,而是安全底线。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











