Java では、mutable 文字列 (変更可能な文字列) を操作する場合、StringBuilder と StringBuffer のどちらかを選択する必要がある場合があります。どちらも値の変更が可能な可変クラスですが、スレッドの安全性、パフォーマンス、アプリケーションの点で大きく異なります。ここでは、それらの特性を比較し、それぞれをいつ使用するかを説明するコード例を示します。
Feature | StringBuilder | StringBuffer |
---|---|---|
Mutability | Mutable | Mutable |
Stored in | Heap (does not use String Pool) | Heap (does not use String Pool) |
Thread Safety | Not thread-safe | Thread-safe |
Synchronization | Not synchronized | Synchronized |
Performance | Faster due to lack of synchronization | Slower due to synchronization overhead |
Use Case | Single-threaded scenarios | Multi-threaded scenarios where thread-safety is required |
各クラスをさらに詳しく見てみましょう。
StringBuilder は 可変 クラスです。つまり、コンテンツの変更が可能です。
スレッドアンセーフであるため、シングルスレッドのシナリオに最適です。
同期されていません: 同期オーバーヘッドがないため、StringBuilder は StringBuffer よりも高速です。
マルチスレッドの制限: 追加の安全対策なしでマルチスレッド環境で StringBuilder を使用すると、競合状態やその他の同時実行の問題が発生する可能性があります。
この例では、2 つのスレッドを使用して文字を StringBuilder インスタンスに追加します。ただし、同期が欠如しているため、競合状態が発生します:
public class StringBuilderBasics { public void threadUnsafe() { // Common resource being shared StringBuilder builder = new StringBuilder(); // Thread appending "A" 1000 times Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { builder.append("A"); } }); // Thread appending "B" 1000 times Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) { builder.append("B"); } }); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } // Result: 1840 (unpredictable) System.out.println("Length: " + builder.toString().length()); } public static void main(String[] args) { new StringBuilderBasics().threadUnsafe(); } }
説明:
スレッドの安全性が確保されていないため、StringBuilder 出力の最終的な長さは予測できません (例: 2000 ではなく 1840 )。
これは、両方のスレッドが同時に文字を追加しようとし、上書き または 操作の削除 が発生するために発生します。
要点: StringBuilder はシングルスレッド環境、またはスレッドセーフが外部で処理される場合にのみ使用してください。
StringBuffer は 変更可能であり、その内容の変更が可能です。
同期されているため、スレッドセーフとなります。
スレッドセーフが必要なマルチスレッド環境に最適です。
パフォーマンス コスト: 同期によりオーバーヘッドが発生するため、StringBuffer は StringBuilder よりも遅い。
これは上記と同じ例ですが、今回は StringBuffer を使用しています:
public class StringBufferBasics { public void threadSafe() { // Common resource being shared StringBuffer buffer = new StringBuffer(); // Thread appending "A" 1000 times Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { buffer.append("A"); } }); // Thread appending "B" 1000 times Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) { buffer.append("B"); } }); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } // Result: 2000 System.out.println("Length: " + buffer.toString().length()); } public static void main(String[] args) { new StringBufferBasics().threadSafe(); } }
説明:
StringBuffer は、両方のスレッドが安全に追加されることを保証し、予想される長さの 2000 を達成します。
最後の文字列はスレッドセーフですが、スレッドの実行順序が 非決定的であるため、出力は インターリーブ (例: 「AAABBB...」が混在する) になる可能性があります。 🎜>.
要点: データの一貫性が重要であり、同期が必要なマルチスレッド アプリケーションには StringBuffer を使用します。
パフォーマンスが重要でスレッドの安全性が考慮されていないシングルスレッドのシナリオでは StringBuilder を使用します。
変更可能な文字列操作が必要で、競合状態を避けるためにスレッドの安全性が必要なマルチスレッド シナリオでは StringBuffer を使用します。
この比較は、StringBuilder と StringBuffer の間で情報に基づいた選択を行うのに役立ちます。可変性、パフォーマンス、スレッドの安全性のトレードオフを理解すると、Java で文字列を操作する際のより適切な意思決定につながる可能性があります。
コーディングを楽しんでください!
以上がJava における StringBuilder と StringBufferの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。