StringBuffer in Java

Learn the thread-safe way to build strings

💡 Think of StringBuffer like a shared whiteboard in a classroom! Multiple students (threads) can use it, but only ONE can write at a time. This prevents chaos and makes sure everyone's writing is clear. StringBuilder is like a personal notepad - faster, but not safe for sharing!

🔒 What is StringBuffer?

StringBuffer is a thread-safe, mutable sequence of characters. It's exactly like StringBuilder, but with synchronized methods that make it safe to use when multiple threads need to modify the same string. This safety comes with a small performance cost.

StringBufferBasics.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class StringBufferBasics {
public static void main(String[] args) {
// Creating StringBuffer (exactly like StringBuilder!)
StringBuffer sb = new StringBuffer("Hello");
// All the same methods work
sb.append(" World");
System.out.println(sb); // Hello World
sb.insert(6, "Beautiful ");
System.out.println(sb); // Hello Beautiful World
sb.reverse();
System.out.println(sb); // dlroW lufituaeB olleH
// The difference? All methods are SYNCHRONIZED
// This makes it safe for multiple threads to use
// but slightly slower than StringBuilder
}
}

⚖️ StringBuilder vs StringBuffer

AspectStringBuilderStringBuffer
Thread SafetyNOT thread-safeThread-safe (synchronized)
PerformanceFaster (no synchronization overhead)Slower (synchronization overhead)
When to UseSingle-threaded applications (most cases)Multi-threaded applications sharing same object

Rule of thumb: Use StringBuilder by default. Only use StringBuffer when multiple threads will access the same object.

🔒 Thread Safety in Action

ThreadSafetyExample.java
java
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class ThreadSafetyExample {
public static void main(String[] args) throws InterruptedException {
// UNSAFE: StringBuilder with multiple threads
StringBuilder unsafeSB = new StringBuilder();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
unsafeSB.append("A");
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
unsafeSB.append("B");
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("StringBuilder length: " + unsafeSB.length());
// Expected: 2000, Actual: might be less! (data loss)
// SAFE: StringBuffer with multiple threads
StringBuffer safeSB = new StringBuffer();
Thread t3 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
safeSB.append("A");
}
});
Thread t4 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
safeSB.append("B");
}
});
t3.start();
t4.start();
t3.join();
t4.join();
System.out.println("StringBuffer length: " + safeSB.length());
// Always: 2000 (thread-safe!)
}
}

🛠️ Common StringBuffer Methods

StringBuffer has the SAME methods as StringBuilder!

  • append() - Add to end
  • insert() - Add at position
  • delete() - Remove characters
  • reverse() - Flip string
  • replace() - Replace characters
  • toString() - Convert to String

📝 Usage Examples

StringBufferUsage.java
java
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
36
37
38
public class StringBufferUsage {
// Shared StringBuffer used by multiple threads
private static StringBuffer sharedLog = new StringBuffer();
public static void main(String[] args) throws InterruptedException {
// Example: Logging from multiple threads
Thread logger1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
logMessage("Thread-1", "Message " + i);
try { Thread.sleep(100); } catch (InterruptedException e) {}
}
});
Thread logger2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
logMessage("Thread-2", "Message " + i);
try { Thread.sleep(100); } catch (InterruptedException e) {}
}
});
logger1.start();
logger2.start();
logger1.join();
logger2.join();
System.out.println("Complete log:");
System.out.println(sharedLog.toString());
}
private static void logMessage(String threadName, String message) {
// StringBuffer is thread-safe, so this is safe
sharedLog.append("[")
.append(threadName)
.append("] ")
.append(message)
.append("\n");
}
}

🤔 When to Use Each?

✅ Use StringBuilder

  • Single-threaded applications (most common)
  • Local variables in methods
  • Building strings in loops
  • When performance is critical

✅ Use StringBuffer

  • Multi-threaded applications
  • Shared objects between threads
  • When thread-safety is required
  • Legacy code that requires it

⚡ Performance Comparison

PerformanceTest.java
java
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
public class PerformanceTest {
public static void main(String[] args) {
int iterations = 100000;
// Test StringBuilder
long start1 = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < iterations; i++) {
sb.append("a");
}
long end1 = System.currentTimeMillis();
// Test StringBuffer
long start2 = System.currentTimeMillis();
StringBuffer sbf = new StringBuffer();
for (int i = 0; i < iterations; i++) {
sbf.append("a");
}
long end2 = System.currentTimeMillis();
System.out.println("StringBuilder time: " + (end1 - start1) + "ms");
System.out.println("StringBuffer time: " + (end2 - start2) + "ms");
// Result: StringBuilder is faster!
// StringBuilder: ~10ms
// StringBuffer: ~12ms (10-20% slower due to synchronization)
}
}

🔑 Key Concepts

Synchronized Methods

All methods are synchronized - only one thread can access at a time

public synchronized StringBuffer append(String str)

Thread-Safe

Multiple threads can safely use the same StringBuffer object

Safe for concurrent modifications from different threads

Performance Trade-off

Synchronization adds overhead, making it slower than StringBuilder

Use only when thread-safety is actually needed

Legacy Class

Introduced in Java 1.0; StringBuilder added in Java 1.5 as faster alternative

For most new code, use StringBuilder instead

⚠️ Common Mistakes

  • 1. Using StringBuffer when StringBuilder would work

    StringBuffer sb = new StringBuffer(); // in single-threaded code

    StringBuilder sb = new StringBuilder(); // faster!

  • 2. Assuming operations are atomic

    // Thread 1 and 2 both: if(sb.length() == 0) sb.append(x);

    // Use explicit synchronization for multi-step operations

  • 3. Using for performance

    StringBuffer sb = new StringBuffer(); // thinking it's faster

    StringBuilder sb = new StringBuilder(); // this is faster!

Best Practices

  • Use StringBuilder unless you specifically need thread-safety
  • Don't use StringBuffer for better performance if threads don't share the object
  • Consider using local variables (StringBuilder) instead of shared StringBuffer
  • If you need thread-safety, StringBuffer is the right choice
  • Remember: methods are synchronized, but sequences of operations are NOT atomic

💼 Interview Tips

  • Know the key difference: StringBuffer is synchronized, StringBuilder is not
  • Understand when to use each: single-threaded vs multi-threaded
  • Remember StringBuffer is slower due to synchronization overhead
  • Both have the same methods - only difference is thread-safety
  • StringBuffer was Java 1.0, StringBuilder added in Java 1.5
  • For new code, default to StringBuilder unless sharing between threads