`StringBuilder` 本身無同步機制,多執行緒並發 `append()` 會導致內部 `char[]` 索引錯位、內容損壞。用 `synchronized` 包裝單個操作或複合操作,**能保證執行緒安全**。
public class SyncStringBuilder {
private final StringBuilder sb = new StringBuilder();
public synchronized void append(String s) { sb.append(s); }
public synchronized String toString() { return sb.toString(); }
// 其他需要原子性的方法同理加 synchronized
}
StringBuilder sb = new StringBuilder();
// 執行緒 A
synchronized(sb) { sb.append("A").append("1"); }
// 執行緒 B
synchronized(sb) { sb.append("B").append("2"); }
| 方案 | 適用場景 | 優缺點 |
|---|---|---|
| StringBuffer | 單純多執行緒 `append`/`toString` | JDK 內建同步、方法級鎖、效能較 `synchronized(StringBuilder)` 差(舊版實現),但零改碼遷移。 |
| ThreadLocal<StringBuilder> | 各執行緒獨立構建,最後合併 | 無鎖、最高效能,需手動合併結果(如日誌收集器)。 |
| java.util.concurrent 匯總器 | 並行流、大量資料聚合 | `StringJoiner`、`Collectors.joining()`、LongAdder 等無鎖設計。 |
| 無鎖 Ring Buffer (Disruptor) | 極高吞吐日誌/事件 | 複雜度高,通常用成熟框架 (Log4j2 AsyncAppender)。 |
StringBuilder + synchronized block : ~45 ms/op
StringBuffer : ~52 ms/op
ThreadLocal + merge : ~12 ms/op
✅ `synchronized` **可行**,適合低併發、舊代碼快速修補。
🚀 新專案或高併發場景,**優先選 `ThreadLocal