Java中StringBuilder和StringBuffer的区别
技术背景
在Java编程里,字符串处理是常见操作。String
类对象是不可变的,每次对String
对象进行修改都会创建新的String
对象,这在频繁修改字符串时会消耗大量内存和性能。为解决此问题,Java提供了StringBuffer
和StringBuilder
类,它们都是可变的字符序列。
实现步骤
1. 基本使用
1 2 3 4 5 6 7 8 9
| StringBuffer stringBuffer = new StringBuffer("Hello"); stringBuffer.append(" World"); System.out.println(stringBuffer.toString());
StringBuilder stringBuilder = new StringBuilder("Hello"); stringBuilder.append(" World"); System.out.println(stringBuilder.toString());
|
2. 多线程环境下使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit;
public class ThreadTest { public static void main(String[] args) throws InterruptedException { StringBuffer stringBuffer = new StringBuffer(); ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { executorService.execute(() -> { for (int j = 0; j < 1000; j++) { stringBuffer.append("a"); } }); } executorService.shutdown(); executorService.awaitTermination(1, TimeUnit.MINUTES); System.out.println("StringBuffer length: " + stringBuffer.length());
StringBuilder stringBuilder = new StringBuilder(); executorService = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { executorService.execute(() -> { for (int j = 0; j < 1000; j++) { stringBuilder.append("a"); } }); } executorService.shutdown(); executorService.awaitTermination(1, TimeUnit.MINUTES); System.out.println("StringBuilder length: " + stringBuilder.length()); } }
|
核心代码
StringBuffer核心方法(部分)
1 2 3 4 5 6 7 8 9 10 11
| public class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence { public synchronized StringBuffer append(Object obj) { super.append(String.valueOf(obj)); return this; }
public synchronized StringBuffer append(String str) { super.append(str); return this; } }
|
StringBuilder核心方法(部分)
1 2 3 4 5 6 7 8 9 10
| public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence { public StringBuilder append(Object obj) { return append(String.valueOf(obj)); }
public StringBuilder append(String str) { super.append(str); return this; } }
|
最佳实践
- 单线程环境:若代码仅在单线程环境运行,推荐使用
StringBuilder
,因其不进行同步操作,性能更佳。
1 2 3 4 5
| StringBuilder sb = new StringBuilder(); for (int i = 0; i < 100; i++) { sb.append(i); } String result = sb.toString();
|
- 多线程环境:若代码在多线程环境运行,且多个线程会同时访问和修改字符串,应使用
StringBuffer
。
1 2 3 4 5 6 7 8 9 10
| StringBuffer sb = new StringBuffer(); Runnable task = () -> { for (int i = 0; i < 100; i++) { sb.append(i); } }; Thread t1 = new Thread(task); Thread t2 = new Thread(task); t1.start(); t2.start();
|
常见问题
1. StringBuffer
是否绝对线程安全?
StringBuffer
的单个方法是线程安全的,但如果涉及多个操作的组合,仍需外部同步。例如,先调用append
再调用toString
,在多线程环境下可能出现问题。
2. 性能差异是否显著?
在单线程环境下,StringBuilder
性能通常优于StringBuffer
,因为StringBuffer
的同步操作会带来一定性能开销。但在某些JVM优化场景下,两者性能差异可能不明显。在多线程环境下,若使用StringBuilder
不进行同步,可能会导致数据不一致问题。