StringBuffer和StringBuilder
在 Java 中,StringBuffer
和StringBuilder
都是用于处理可变字符串的类,它们都继承自AbstractStringBuilder
,提供了类似的 API(如append()
、insert()
、delete()
等)来修改字符串内容。但两者在线程安全性和性能上有显著区别。
一、核心区别
特性 | StringBuffer | StringBuilder |
---|---|---|
线程安全性 | 线程安全(同步方法) | 非线程安全(无同步机制) |
性能 | 较低(同步开销) | 较高(无同步开销) |
出现版本 | Java 1.0 | Java 5.0 |
适用场景 | 多线程环境 | 单线程环境 |
二、详细解析
1. 线程安全性
StringBuffer
:所有修改方法(如append()
、insert()
)都被synchronized
修饰,确保多线程环境下操作的原子性,因此是线程安全的。源码示例(
StringBuffer
的append
方法):@Override public synchronized StringBuffer append(String str) {toStringCache = null;super.append(str);return this; }
StringBuilder
:方法没有synchronized
修饰,在多线程同时修改时可能出现数据不一致,因此是非线程安全的。源码示例(
StringBuilder
的append
方法):@Override public StringBuilder append(String str) {super.append(str);return this; }
2. 性能差异
StringBuilder
性能更高:由于避免了synchronized
带来的锁竞争和上下文切换开销,在单线程环境下,StringBuilder
的操作速度通常比StringBuffer
快 10%-15%。StringBuffer
性能较低:同步机制保证了线程安全,但牺牲了部分性能。
3. 使用场景
优先使用
StringBuilder
:- 单线程环境(如普通的方法内部处理字符串)。
- 对性能要求较高,且不存在多线程并发修改的场景。
示例:
// 单线程字符串拼接 StringBuilder sb = new StringBuilder(); for (int i = 0; i < 100; i++) {sb.append(i); // 高效,无同步开销 } String result = sb.toString();
使用
StringBuffer
:- 多线程环境,且多个线程可能同时修改同一个字符串对象(如共享的全局变量)。
示例:
// 多线程共享的字符串缓冲区 public class SharedBuffer {private StringBuffer buffer = new StringBuffer();// 多线程可能同时调用此方法public void addMessage(String msg) {buffer.append(msg).append("\n"); // 同步方法,线程安全} }
三、与String
的对比
StringBuffer
和StringBuilder
的共同优势是可变,与String
(不可变)相比:
String
每次修改都会创建新对象,浪费内存和时间(如循环拼接字符串时)。StringBuffer
/StringBuilder
直接在内部字符数组上修改,避免频繁创建对象,效率更高。反例(低效的
String
拼接):String s = ""; for (int i = 0; i < 1000; i++) {s += i; // 每次都会创建新String对象,性能差 }
四、总结
- 单线程环境:优先用
StringBuilder
,追求更高性能。 - 多线程环境:必须用
StringBuffer
,保证线程安全。 - 两者 API 完全一致,替换使用时只需修改类名即可。
在实际开发中,单线程场景更为常见,因此StringBuilder
的使用频率更高。只有当明确需要在多线程中共享并修改字符串时,才考虑StringBuffer
。