StringBuffer
Thread-safe mutable strings
Interview Relevant: StringBuffer vs StringBuilder interview question
5 min read
StringBuffer - Thread-Safe Mutable Strings
StringBuffer is the thread-safe version of StringBuilder. All its methods are synchronized, making it safe for concurrent access.
StringBuffer vs StringBuilder
| Feature | StringBuilder | StringBuffer |
|---|---|---|
| Thread Safety | ❌ Not thread-safe | ✅ Thread-safe |
| Performance | Faster | Slower (synchronization) |
| Introduced | Java 5 | Java 1.0 |
| When to Use | Single-threaded | Multi-threaded |
💡 Rule of Thumb: Use StringBuilder unless you specifically need thread safety. In 99% of cases, StringBuilder is the better choice.
Code Examples
Basic StringBuffer operations (same as StringBuilder)
java
1// Creating StringBuffer
2StringBuffer sb1 = new StringBuffer(); // Empty, capacity 16
3StringBuffer sb2 = new StringBuffer(100); // Empty, capacity 100
4StringBuffer sb3 = new StringBuffer("Hello"); // From String
5
6// All methods are same as StringBuilder
7StringBuffer sb = new StringBuffer("Hello");
8sb.append(" World"); // "Hello World"
9sb.insert(5, ","); // "Hello, World"
10sb.reverse(); // "dlroW ,olleH"
11sb.reverse(); // "Hello, World"
12sb.delete(5, 7); // "Hello World"
13
14String result = sb.toString();
15
16// The only difference is thread safety!Thread safety in concurrent access
java
1// Thread safety demonstration
2// StringBuffer is safe for concurrent access
3
4StringBuffer sharedBuffer = new StringBuffer();
5
6// Multiple threads can safely modify
7Thread t1 = new Thread(() -> {
8 for (int i = 0; i < 1000; i++) {
9 sharedBuffer.append("A");
10 }
11});
12
13Thread t2 = new Thread(() -> {
14 for (int i = 0; i < 1000; i++) {
15 sharedBuffer.append("B");
16 }
17});
18
19t1.start();
20t2.start();
21t1.join();
22t2.join();
23
24// Result will have exactly 2000 characters (1000 A's + 1000 B's)
25System.out.println(sharedBuffer.length()); // 2000
26
27// With StringBuilder, the result would be UNPREDICTABLE!
28// StringBuilder is NOT thread-safePerformance difference due to synchronization
java
1// Performance comparison
2int iterations = 100000;
3
4// StringBuilder (faster for single-threaded)
5long start1 = System.currentTimeMillis();
6StringBuilder sb = new StringBuilder();
7for (int i = 0; i < iterations; i++) {
8 sb.append(i);
9}
10long time1 = System.currentTimeMillis() - start1;
11
12// StringBuffer (slower due to synchronization)
13long start2 = System.currentTimeMillis();
14StringBuffer sbf = new StringBuffer();
15for (int i = 0; i < iterations; i++) {
16 sbf.append(i);
17}
18long time2 = System.currentTimeMillis() - start2;
19
20System.out.println("StringBuilder: " + time1 + "ms");
21System.out.println("StringBuffer: " + time2 + "ms");
22
23// StringBuffer is typically 10-20% slowerAppropriate use cases for StringBuffer
java
1// When to use StringBuffer
2
3// 1. Shared buffer in multi-threaded logger
4public class ThreadSafeLogger {
5 private final StringBuffer log = new StringBuffer();
6
7 public void log(String message) {
8 // Thread-safe append
9 log.append(Thread.currentThread().getName())
10 .append(": ")
11 .append(message)
12 .append("\n");
13 }
14
15 public String getLog() {
16 return log.toString();
17 }
18}
19
20// 2. Building output from multiple threads
21StringBuffer result = new StringBuffer();
22ExecutorService executor = Executors.newFixedThreadPool(4);
23
24for (int i = 0; i < 10; i++) {
25 final int id = i;
26 executor.submit(() -> {
27 result.append("Task " + id + " completed\n");
28 });
29}
30
31// 3. Modern alternative: Consider other thread-safe options
32// - ConcurrentHashMap for key-value
33// - CopyOnWriteArrayList for lists
34// - Or use StringBuilder with external synchronizationUse Cases
- Multi-threaded string building
- Shared log buffers
- Concurrent text processing
- Legacy code maintenance
- Thread-safe output building
- Synchronized string manipulation
Common Mistakes to Avoid
- Using StringBuffer when StringBuilder is sufficient
- Assuming StringBuffer is always needed for safety
- Not realizing synchronization overhead
- Using in single-threaded code unnecessarily
- Forgetting external synchronization for compound operations
- Not converting to String when needed