StringBuilderとStringBufferの違い


回答:


1666

StringBuffer同期されてStringBuilderいますが、同期されていません。


239
また、StringBuilderは、同期が不要なStringBufferに代わるドロップとして意図されています
Joel

95
同期は実質的に必要ありません。誰かがStringBuilderで同期したい場合は、コードブロック全体をインスタンスの同期済み(sb){}で囲むだけです
locka

23
@locka私はStringBufferのは良いアイデア(あなたがそれを必要とするAPIを持っていない限り)決してないことを主張したいvanillajava.blogspot.de/2013/04/...
ピーターLawrey

8
StringBufferで私が見る場所は、コンソールのような出力とさまざまなロギングユーティリティだけです。多くのスレッドが競合して出力する可能性があります。2つの出力が混同されたくないためですが、通常、StringBufferレベルでの同期はレベルが低すぎるため、levelmなどのアペンダーで同期したいので、lockaの回答が最適であり、StringBufferは非推奨にする必要があります。初心者の場合、コードレビューの時間を節約できます。
Remi Morin

20
これら2つを混在させる人にとっては良いニーモニック-BuFFerが最初で、古く、したがって同期された実装でした。新しいビルダークラスはビルダーパターンを使用し、非同期です。
Datageek、

728

StringBuilderそれはそうではStringBufferないのでより速いですsynchronized

簡単なベンチマークテストは次のとおりです。

public class Main {
    public static void main(String[] args) {
        int N = 77777777;
        long t;

        {
            StringBuffer sb = new StringBuffer();
            t = System.currentTimeMillis();
            for (int i = N; i --> 0 ;) {
                sb.append("");
            }
            System.out.println(System.currentTimeMillis() - t);
        }

        {
            StringBuilder sb = new StringBuilder();
            t = System.currentTimeMillis();
            for (int i = N; i > 0 ; i--) {
                sb.append("");
            }
            System.out.println(System.currentTimeMillis() - t);
        }
    }
}

テストの実行は、数を与える2241 msためにStringBuffer753 msのためStringBuilder


10
文字列リテラルをより大きな「クイックブラウンフォックス」に変更し、より興味深い結果を得ました。基本的に、それらはほぼ同じくらい高速です。実際にメモリが足りなくなったので、7をいくつか削除する必要がありました。説明:同期はホットスポットによって最適化されます。あなたは基本的に、ホットスポットがこれを行うのに必要な時間を測定しているだけです(そしておそらくさらに最適化されています)。
Jilles van Gurp、2012

7
前にウォームアップする必要があります。このテストは、StringBufferに対して不公平です。また、実際に何かを付け加えたらいいですね。実際、私はテストをひっくり返し、ランダムな文字列を追加して、反対のテストを行いました。単純なベンチマークを信頼することはできないと言います。反対は、StringBufferの方が速いことを示しています。StringBuilderの場合は5164、StringBufferの場合は3699 hastebin.com/piwicifami.avrasm
mmm

75
これは私--> 0がループで見るのは初めてです。それが何を意味するのか理解するのに少し時間がかかりました。これは通常の...; i > 0; i--構文の代わりに実際に実際に使用されているものですか?
RaimundKrämer15年

19
それはi -->、私はそれが理由ASCIIアートについてのコメントの最初にある矢印だと思った...本当に迷惑構文が賢明です。
Sameer Puri

14
他の人は異なる結果で結論を出します:alblue.bandlem.com/2016/04/jmh-stringbuffer-stringbuilder.html。ベンチマークは、単純なものではなく、JMHで実際に実行する必要がありmain()ます。また、ベンチマークは不公平です。ウォームアップはありません。
Lukas Eder 2017年

249

基本的に、StringBufferメソッドは同期されますが、同期さStringBuilderれません。

操作は「ほぼ」同じですが、単一のスレッドで同期メソッドを使用するのはやりすぎです。

それはほとんどそれについてです。

StringBuilder APIからの引用:

このクラス[StringBuilder]は、StringBufferと互換性のあるAPIを提供しますが、同期の保証はありません。このクラスは、文字列バッファーが単一のスレッドによって使用されていた場所(一般的なケース)で、StringBufferのドロップイン置換として使用するために設計されています。ほとんどの実装では高速になるため、可能であれば、このクラスをStringBufferよりも優先して使用することをお勧めします。

だからそれを置き換えるために作られました。

同じことがVectorとでも起こりましたArrayList


1
また、HashtableHashMap
shmosel 2017年

177

しかし、例を使用して明確な違いを得る必要がありますか?

StringBufferまたはStringBuilder

StringBuilder本当にスレッド間でバッファを共有しようとしているのでない限り、単に使用してください。StringBuilder同期されていない(オーバーヘッドが少ない=より効率的な)元の同期されたStringBufferクラスの弟です。

StringBuffer最初に来ました。Sunはすべての条件下での正確性に関心を持っていたため、念のためにスレッドセーフにするために同期させました。

StringBuilder後で来ました。の使用のほとんどStringBufferはシングルスレッドであり、同期のコストを不必要に支払っていました。

ためStringBuilderであるドロップイン交換StringBuffer同期せずに、任意の実施例の違いは存在しないであろう。

あなたがいる場合しているスレッド間で共有しようと、あなたが使用することができStringBuffer、おそらく代わりにStringBufferを使用するなど、より高いレベルの同期が必要であるかどうかを検討し、あなたはStringBuilderのを使用する方法を同期させる必要があります。


14
最初の良い答え!重要なのは、「スレッド間でバッファを共有していない限り」
AlexWien

1
非常に詳細な回答!
ラウル・

81

最初に類似点を見てみましょう。StringBuilderとStringBufferはどちらも変更可能です。つまり、同じ場所でそれらのコンテンツを変更できます。

相違点:StringBufferは変更可能であり、同期も行われます。StringBuilderは変更可能ですが、デフォルトでは同期されていません。

同期(同期)の意味:何かが同期されると、複数のスレッドがアクセスし、問題や副作用なしに変更できます。StringBufferは同期されるため、問題なく複数のスレッドで使用できます。

どれを使うの? StringBuilder:変更可能な文字列が必要で、1つのスレッドのみがその文字列にアクセスして変更している場合。StringBuffer:変更可能な文字列が必要で、複数のスレッドがその文字列にアクセスして変更している場合。

:StringBufferを不必要に使用しないでください。つまり、1つのスレッドだけが変更してアクセスしている場合は、使用しないでください。同期のためのロックおよびロック解除コードが多く、CPU時間を不必要に消費します。必要でない限り、ロックを使用しないでください。


2
StringBufferのINDIVIDUALメソッドの呼び出しはスレッドセーフであることを述べたいだけです。ただし、複数行のコードがある場合は、同期されたコードブロックを使用して、スレッドの安全性を保証し、(通常のように)ロック/モニターを使用します。基本的に、スレッドセーフライブラリを使用することで、プログラムのスレッドセーフが即座に保証されるとは限りません。
ケビン・リー

57

シングルスレッドで、JVMの最適化により、StringBufferはStringBuilderよりも大幅に遅くなることはありません。マルチスレッドでは、StringBuilderを安全に使用することはできません。

これが私のテストです(ベンチマークではなく、単なるテストです):

public static void main(String[] args) {

    String withString ="";
    long t0 = System.currentTimeMillis();
    for (int i = 0 ; i < 100000; i++){
        withString+="some string";
    }
    System.out.println("strings:" + (System.currentTimeMillis() - t0));

    t0 = System.currentTimeMillis();
    StringBuffer buf = new StringBuffer();
    for (int i = 0 ; i < 100000; i++){
        buf.append("some string");
    }
    System.out.println("Buffers : "+(System.currentTimeMillis() - t0));

    t0 = System.currentTimeMillis();
    StringBuilder building = new StringBuilder();
    for (int i = 0 ; i < 100000; i++){
        building.append("some string");
    }
    System.out.println("Builder : "+(System.currentTimeMillis() - t0));
}

結果:
文字列:319740
バッファー:23
ビルダー:7!

そのため、ビルダーはバッファよりも高速で、文字列の連結よりも高速です。次に、Executorを複数のスレッドに使用します。

public class StringsPerf {

    public static void main(String[] args) {

        ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
        //With Buffer
        StringBuffer buffer = new StringBuffer();
        for (int i = 0 ; i < 10; i++){
            executorService.execute(new AppendableRunnable(buffer));
        }
        shutdownAndAwaitTermination(executorService);
        System.out.println(" Thread Buffer : "+ AppendableRunnable.time);

        //With Builder
        AppendableRunnable.time = 0;
        executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
        StringBuilder builder = new StringBuilder();
        for (int i = 0 ; i < 10; i++){
            executorService.execute(new AppendableRunnable(builder));
        }
        shutdownAndAwaitTermination(executorService);
        System.out.println(" Thread Builder: "+ AppendableRunnable.time);

    }

   static void shutdownAndAwaitTermination(ExecutorService pool) {
        pool.shutdown(); // code reduced from Official Javadoc for Executors
        try {
            if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
                pool.shutdownNow();
                if (!pool.awaitTermination(60, TimeUnit.SECONDS))
                    System.err.println("Pool did not terminate");
            }
        } catch (Exception e) {}
    }
}

class AppendableRunnable<T extends Appendable> implements Runnable {

    static long time = 0;
    T appendable;
    public AppendableRunnable(T appendable){
        this.appendable = appendable;
    }

    @Override
    public void run(){
        long t0 = System.currentTimeMillis();
        for (int j = 0 ; j < 10000 ; j++){
            try {
                appendable.append("some string");
            } catch (IOException e) {}
        }
        time+=(System.currentTimeMillis() - t0);
    }
}

StringBuffersが100000回の追加に157ミリ秒かかるようになりました。これは同じテストではありませんが、直前の37ミリ秒と比較すると、マルチスレッドを使用すると、StringBuffersの追加が遅いと安全に想定できます。その理由は、JIT /ホットスポット/コンパイラ/何かがロックをチェックする必要がないことを検出したときに最適化を行うためです。

しかし、StringBuilderを使用すると、並行スレッドが何かを追加してはいけない場所に追加しようとするため、java.lang.ArrayIndexOutOfBoundsExceptionが発生します

結論として、StringBuffersを追跡する必要はありません。スレッドがある場合は、数ナノ秒を獲得しようとする前に、スレッドが何をしているかを考えます。


5
「t0 = System.currentTimeMillis();」を行うのを忘れた StringBuilderテストを行う前。したがって、StringBuilderに表示される数値は、実際にはstringbuffer AND stringbuilderテストの実行にかかった時間です。この行を追加すると、StringBuilderが2倍高速であることがわかります。
Gena Batsyan 2013

withString+="some string"+i+" ; ";は他の2つのループと同等ではないため、公平な比較ではありません。
デイブジャービス

正確、修正済み。思考の文字列はまだ非常に遅いです。
Nicolas Zozol、2015年

あなたはより多くの理由を説明することができますは、ArrayIndexOutOfBoundsExceptionのための昇給のStringBuilderを
アリレザFattahi

ベンチマークにはJMHを使用する必要があります。あなたのベンチマークは本当に不正確です。
Lukas Eder

42

StringBuilderはJava 1.5で導入されたため、以前のJVMでは動作しません。

Javadocsから:

StringBuilderクラスは、StringBufferと互換性のあるAPIを提供しますが、同期の保証はありません。このクラスは、文字列バッファが単一のスレッドで使用されていた場所(通常の場合)でStringBufferのドロップイン置換として使用するために設計されています。ほとんどの実装では高速になるため、可能であれば、このクラスをStringBufferよりも優先して使用することをお勧めします。


13
1.4はサービス期間が終了したため、1.5より前のバージョンについて心配する価値はほとんどありません。
トム・ホーティン-タックライン2008

@ tomHawtin-tacklineは必ずしも必要ではありません。1.4より前のバージョンには、ほとんどの人が毎日使用しているエンタープライズ製品があります。また、BlackBerry Javaは1.4に基づいており、それはまだ非常に最新です。
Richard Le Mesurier 2013年

CDCとCLDCにはありませんStringBuilder
ジンクォン2013

37

かなり良い質問

ここに違いがあります、私は気づきました:

StringBuffer:-

StringBuffer is  synchronized
StringBuffer is  thread-safe
StringBuffer is  slow (try to write a sample program and execute it, it will take more time than StringBuilder)

StringBuilder:-

 StringBuilder is not synchronized 
 StringBuilder is not thread-safe
 StringBuilder performance is better than StringBuffer.

一般的なこと:-

どちらも同じシグネチャを持つ同じメソッドを持っています。どちらも変更可能です。


23

StringBuffer

  • 同期されているためスレッドセーフ
  • スレッドセーフなので低速

StringBuilder

  • Java 5.0で導入
  • 非同期であるため高速で効率的
  • ユーザーは、必要に応じて明示的に同期する必要があります
  • StringBuffer他の変更なしで交換できます

注:スレッドセーフなのは単一の操作のみで、複数の操作はそうではありません。たとえば、append2回電話した場合やappendtoString安全でない場合などです。
Peter Lawrey

22

StringBuilderはスレッドセーフではありません。文字列バッファです。詳細はこちら

編集:パフォーマンスに関しては、ホットスポットが始まった後、StringBuilderが勝者です。ただし、小さな反復の場合、パフォーマンスの違いはごくわずかです。


21

StringBuilderStringBufferほとんど同じです。違いは、StringBuffer同期されることと同期されStringBuilderないことです。ただし、StringBuilderより高速ですStringBuffer、パフォーマンスの違いはごくわずかです。StringBuilderSUNのの置き換えですStringBuffer。すべてのパブリックメソッドからの同期を回避するだけです。むしろ、それらの機能は同じです。

良い使い方の例:

テキストが変更され、複数のスレッドで使用される場合は、を使用することをお勧めしますStringBuffer。テキストが変更されるが、シングルスレッドで使用される場合は、を使用しますStringBuilder


19

StringBuffer

StringBufferは可変なので、オブジェクトの値を変更できます。StringBufferを通じて作成されたオブジェクトは、ヒープに格納されます。StringBufferにはStringBuilderと同じメソッドがありますが、StringBufferの各メソッドは同期されます。つまり、StringBufferはスレッドセーフです。

このため、2つのスレッドが同じメソッドに同時にアクセスすることはできません。各メソッドには、一度に1つのスレッドからアクセスできます。

ただし、スレッドセーフであることにはStringBufferのパフォーマンスが影響するため、スレッドセーフであることにも欠点があります。したがって、各クラスの同じメソッドを呼び出す場合、StringBuilderはStringBufferよりも高速です。

StringBuffer値は変更できます。つまり、新しい値に割り当てることができます。今日、これは最も一般的なインタビューの質問です。上記のクラスの違いです。文字列バッファは、toString()メソッドを使用して文字列に変換できます。

StringBuffer demo1 = new StringBuffer(“Hello”) ;
// The above object stored in heap and its value can be changed .

demo1=new StringBuffer(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuffer

StringBuilder

StringBuilderはStringBufferと同じです。つまり、オブジェクトをヒープに格納し、変更することもできます。StringBufferとStringBuilderの主な違いは、StringBuilderもスレッドセーフではないことです。StringBuilderはスレッドセーフではないため高速です。

StringBuilder demo2= new StringBuilder(“Hello”);
// The above object too is stored in the heap and its value can be modified

demo2=new StringBuilder(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuilder

ここに画像の説明を入力してください

リソース:String Vs StringBuffer Vs StringBuilder


StringBuilderは不変で、String型は変更可能
Brinda Rathod '15年

StringsとStringBuildersが「高速」で、StringBufferが「非常に遅い」ということに同意しません。上記の回答を参照してください。
FireCubez

17

String 不変です。

StringBuffer 変更可能で同期されています。

StringBuilder も変更可能ですが、同期されていません。


さらに、StringBufferは、このスレッドセーフデータにアクセスするためにスレッドをロックします。そのため、操作が遅くなります。StringBuilderはスレッドをロックせず、マルチスレッドで実行されるので高速です。文字列-文字列を連結する必要がない場合はこれが良い方法ですが、必要な場合はStringBuilderを使用します。Stringはヒープ内に新しいオブジェクトが作成されるたびに作成されますが、StringBuilderは同じオブジェクトを返します...
Musa

11

Javadocは違いを説明します。

このクラスは、StringBufferと互換性のあるAPIを提供しますが、同期の保証はありません。このクラスは、文字列バッファーが単一のスレッドによって使用されていた場所(一般的なケース)で、StringBufferのドロップイン置換として使用するために設計されています。ほとんどの実装では高速になるため、可能であれば、このクラスをStringBufferよりも優先して使用することをお勧めします。


10

StringBuilder(Java 5で導入)はStringBuffer、メソッドが同期されないことを除いて、と同じです。つまり、後者よりもパフォーマンスが優れていますが、スレッドセーフではないという欠点があります。

読むチュートリアル詳細。


6

StringBufferとStringBuilderの違いを示す簡単なプログラム:

/**
 * Run this program a couple of times. We see that the StringBuilder does not
 * give us reliable results because its methods are not thread-safe as compared
 * to StringBuffer.
 * 
 * For example, the single append in StringBuffer is thread-safe, i.e.
 * only one thread can call append() at any time and would finish writing
 * back to memory one at a time. In contrast, the append() in the StringBuilder 
 * class can be called concurrently by many threads, so the final size of the 
 * StringBuilder is sometimes less than expected.
 * 
 */
public class StringBufferVSStringBuilder {

    public static void main(String[] args) throws InterruptedException {

        int n = 10; 

        //*************************String Builder Test*******************************//
        StringBuilder sb = new StringBuilder();
        StringBuilderTest[] builderThreads = new StringBuilderTest[n];
        for (int i = 0; i < n; i++) {
            builderThreads[i] = new StringBuilderTest(sb);
        }
        for (int i = 0; i < n; i++) {
            builderThreads[i].start();
        }
        for (int i = 0; i < n; i++) {
            builderThreads[i].join();
        }
        System.out.println("StringBuilderTest: Expected result is 1000; got " + sb.length());

        //*************************String Buffer Test*******************************//

        StringBuffer sb2 = new StringBuffer();
        StringBufferTest[] bufferThreads = new StringBufferTest[n];
        for (int i = 0; i < n; i++) {
            bufferThreads[i] = new StringBufferTest(sb2);
        }
        for (int i = 0; i < n; i++) {
            bufferThreads[i].start();
        }
        for (int i = 0; i < n; i++) {
            bufferThreads[i].join();
        }
        System.out.println("StringBufferTest: Expected result is 1000; got " + sb2.length());

    }

}

// Every run would attempt to append 100 "A"s to the StringBuilder.
class StringBuilderTest extends Thread {

    StringBuilder sb;

    public StringBuilderTest (StringBuilder sb) {
        this.sb = sb;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            sb.append("A");
        }

    }
}


//Every run would attempt to append 100 "A"s to the StringBuffer.
class StringBufferTest extends Thread {

    StringBuffer sb2;

    public StringBufferTest (StringBuffer sb2) {
        this.sb2 = sb2;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            sb2.append("A");
        }

    }
}

4

StringBufferは、変更される文字列を格納するために使用されます(Stringオブジェクトは変更できません)。必要に応じて自動的に拡張されます。関連クラス:String、CharSequence。

StringBuilderはJava 5で追加されました。StringBufferは、同期されていないことを除いて、すべての点で同じです。つまり、複数のスレッドが同時にアクセスすると問題が発生する可能性があります。最も一般的なシングルスレッドプログラムの場合、同期のオーバーヘッドを回避することで、StringBuilderの速度がわずかに速くなります。


4
シングルスレッドプログラムはJavaで最も一般的なケースではありませんStringBuilderが、通常、‍はメソッドに対してローカルであり、1つのスレッドにのみ表示されます。
finnw '25年

4

StringBuffer同期されてStringBuilderいますが、同期されていません。その結果、StringBuilderはより高速ですStringBuffer


4

StringBuffer は変更可能です。長さと内容の点で変わる可能性があります。StringBufferはスレッドセーフです。つまり、アクセスを制御する同期メソッドがあり、一度に1つのスレッドのみがStringBufferオブジェクトの同期コードにアクセスできます。したがって、StringBufferオブジェクトは、複数のスレッドが同じStringBufferオブジェクトに同時にアクセスしようとしている可能性があるマルチスレッド環境で使用しても安全です。

StringBuilder StringBuilderクラスはStringBufferに非常に似ていますが、そのアクセスは同期されないため、スレッドセーフではありません。同期されないことにより、StringBuilderのパフォーマンスはStringBufferよりも優れている場合があります。したがって、シングルスレッド環境で作業している場合、StringBufferの代わりにStringBuilderを使用すると、パフォーマンスが向上する可能性があります。これは、1つのスレッドのみがStringBuilderオブジェクトにアクセスするStringBuilderローカル変数(つまり、メソッド内の変数)などの他の状況にも当てはまります。


4

StringBuffer:

  • マルチスレッド
  • 同期済み
  • StringBuilderより遅い

StringBuilder

  • シングルスレッド
  • 同期されていません
  • これまでにないストリング

2
より正確にString c = a + bは、と同等であるためString c = new StringBuilder().append(a).append(b).toString()、高速ではありません。それはあなたが1つしかない可能性がありながら、あなたは、各文字列の逢引のために新しいものを作成することだけです(String d = a + b; d = d + c;あるString d = new StringBuilder().append(a).append(b).toString(); d = new StringBuilder().append(d).append(c).toString();一方、StringBuilder sb = new StringBuilder(); sb.append(a).append(b); sb.append(c); String d = sb.toString();1つのStringBuilderインスタンス化を保存します)。
2015年

4

文字列ビルダー

int one = 1;
String color = "red";
StringBuilder sb = new StringBuilder();
sb.append("One=").append(one).append(", Color=").append(color).append('\n');
System.out.print(sb);
// Prints "One=1, Colour=red" followed by an ASCII newline.

文字列バッファ

StringBuffer sBuffer = new StringBuffer("test");
sBuffer.append(" String Buffer");
System.out.println(sBuffer);  

StringBufferよりも高速であるため、可能な場合は常にStringBuilderを使用することをお勧めします。ただし、スレッドセーフが必要な場合、最良のオプションはStringBufferオブジェクトです。


スレッドセーフが必要な場合、最善のオプションは、StringBuilderを使用することです。StringBufferは、個々の操作に対してのみスレッドセーフです。複数の操作の場合、明示的なロックが必要です。
Peter Lawrey

4

同期されていないため、より適切に使用できStringBuilder、パフォーマンスが向上します。あるドロップイン置換古いのは。StringBuilderStringBuffer


3
@Markはtrueですが、ほとんどの場合、これStringBu(ff|ild)erは単一のスレッドでのみ使用されるローカル変数です。
gabuzo、2011年

1
@MarkMcKenna:マルチスレッドアプリケーションであっても、多くの場合、外部ロックを使用するか、それを回避するために追加の作業を行う必要があります。たとえば、2つのスレッドがそれぞれ複数の文字列を含むレコードを文字列ビルダーに追加する場合、追加するデータを集約し、より高速であったとしても、それを1つの単位として追加する必要があります(スレッドの問題がない場合)。一連の個別の追加操作を単純に実行します。
スーパーキャット2014年

3

以来StringBuffer同期され、それが故にperforamance、遅いよりもそのAビットに基づいて、いくつかの余分な労力を必要としますStringBuilder


3

間には基本的な違いはありませんStringBuilderStringBuffer、ほんのわずかな違いは、それらの間に存在します。ではStringBufferメソッド同期されます。これは、一度に1つのスレッドしか操作できないことを意味します。複数のスレッドがある場合、2番目のスレッドは最初のスレッドが終了するのを待たなければならず、3番目のスレッドは最初と2番目のスレッドが終了するのを待たなければなりません。これにより、プロセスが非常に遅くなるため、StringBufferは低くなります。

一方、StringBuilder同期されていません。これは、同時に複数のスレッドが同じStringBuilderオブジェクトを同時に操作できることを意味します。これによりプロセスが非常に高速になり、パフォーマンスStringBuilderが高くなります。


3

AはString意味不変オブジェクトである値を変更することができないのに対し、StringBuffer可変です。

StringBufferしたがって、スレッドセーフをに対し同期されるStringBuilder単一スレッド・インスタンスには適していないと。


3
StringBufferがコードを同期しているからといって、必ずしもStringBufferがスレッドセーフであるとは限りません。次の例を考えてみましょう:StringBuffer TestingBuffer = "stackoverflow"; ここで、スレッド1はTestingBufferに「1」を追加しようとし、スレッド2はTestingBufferに「2」を追加しようとします。現在、append()メソッドは同期されていますが、testingBufferの値が "stackoverflow12"か "stackoverflow21"かはわかりません。実際には、文字列バッファではなく文字列ビルダーを使用することをお勧めします。これがお役に立てば幸いです:)
Biman Tripathy

2

主な違いはされStringBuffersyncronizedされますが、StringBuilderあなたが複数のスレッドを使用する必要がnot.If実行速度ごととして、その後のStringBufferは、recommended.ButですStringBuilder速くよりもStringBufferそのはsyncronizedないので、。


4
StringBufferは、1つの操作のみを実行する場合にのみスレッドセーフです。マルチスレッドでの使用はお勧めしません。正しく理解するのが非常に難しいからです。
Peter Lawrey

@PeterLawreyどういう意味ですか?:-)
Tamad Lang

1
@ b16db0つまり、外部同期なしでStringBufferを複数回呼び出してクラスを無意味にするため、StringBufferのほとんどの使用はスレッドセーフではありません。
Peter Lawrey、2014

@PeterLawreyああ、それはStringBufferがまだ同期環境を必要としているようなものです。
Tamad Lang

2

同期のappendメソッドの内部チェックStringBufferとの非同期appendメソッドをStringBuilder

StringBuffer

public StringBuffer(String str) {
    super(str.length() + 16);
    append(str);
}

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

public StringBuilder(String str) {
    super(str.length() + 16);
    append(str);
}

public StringBuilder append(Object obj) {
    return append(String.valueOf(obj));
}

public StringBuilder append(String str) {
    super.append(str);
    return this;
}

追記であるのでsynchronizedStringBufferと比較して、パフォーマンス・オーバーヘッドを有するStrinbBuilderシナリオをマルチスレッド。複数のスレッド間でバッファを共有しない限り、を使用してくださいStringBuilder。これはsynchronized、appendメソッドがないため高速です。


1

以下は、String vs StringBuffer vs StringBuilderのパフォーマンステスト結果です。最後に、StringBuilderがテストで優勝しました。テストコードと結果については、以下を参照してください。

コード

private static void performanceTestStringVsStringbuffereVsStringBuilder() {
// String vs StringBiffer vs StringBuilder performance Test

int loop = 100000;
long start = 0;

// String
String str = null;
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
  str += i + "test";
}
System.out.println("String - " + (System.currentTimeMillis() - start) + " ms");

// String buffer
StringBuffer sbuffer = new StringBuffer();
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
  sbuffer.append(i).append("test");
}
System.out.println("String Buffer - " + (System.currentTimeMillis() - start) + " ms");

// String builder
start = System.currentTimeMillis();
StringBuilder sbuilder = new StringBuilder();
for (int i = 1; i <= loop; i++) {
  sbuffer.append(i).append("test");
}
System.out.println("String Builder - " + (System.currentTimeMillis() - start) + " ms");

  }

ideoneで私を実行

結果

1つのテキストを追加するための100000回の反復

String - 37489 ms
String Buffer - 5 ms
String Builder - 4 ms

単一のテキストを追加するための10000回の反復

String - 389 ms
String Buffer - 1 ms
String Builder - 1 ms

1
  • StringBufferはスレッドセーフですが、StringBuilderはスレッドセーフではありません。
  • StringBuilderはStringBufferより高速です。
  • StringBufferは同期されますが、StringBuilderは同期されません。

1

StringBufferは同期され、スレッドセーフです。StringBuilderは同期されず、高速です。


この違いは、この質問に対する他のすべての回答で示されています。新しいことを強調していただけますか?
Nico Haase
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.