web-dev-qa-db-ja.com

StringBuilderを使用する理由StringBufferは、1つのスレッドだけでなく複数のスレッドでも機能しますか?

アプリケーションにスレッドが1つしかないとします。 StringBufferを使用している場合、問題は何ですか?

つまり、StringBufferが同期を通じて複数のスレッドを処理できる場合、単一のスレッドで作業する場合の問題は何ですか?

代わりにStringBuilderを使用するのはなぜですか?

16
MANISH PATHAK

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

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

したがって、StringBuilderを優先します。なぜなら、

  • パフォーマンスのわずかな向上。
  • StringBuilderは、StringBufferクラスの1:1ドロップイン置換です。
  • StringBuilderはスレッド同期されていないため、Javaのほとんどの実装でパフォーマンスが向上します。

これをチェックしてください:

27
sgokhales

StringBuilderは同期されていない(スレッドセーフ)ため、(小さな)少し速いはずです。

非常に重いアプリケーションの違いに気付くでしょう。

StringBuilderクラスは、同じ操作をすべてサポートするため、通常はこれよりも優先して使用する必要がありますが、同期を実行しないため、より高速です。

http://download.Oracle.com/javase/6/docs/api/Java/lang/StringBuffer.html

7

複数のスレッドでStringBufferを使用することはほとんど役に立たず、実際にはほとんど起こりません。

次のことを考慮してください

Thread1: sb.append(key1).append("=").append(value1);
Thread2: sb.append(key2).append("=").append(value2);

各追加は同期されますが、スレッドはいつでもかがむことができるため、次の組み合わせなどを使用できます。

key1=value1key2=value2
key1key2==value2value1
key2key1=value1=value2
key2=key1=value2value1

これは、一度に行全体を同期することで回避できますが、これは、StringBuilderの代わりにStringBufferを使用するという点を無効にします。

正しく同期されたビューがある場合でも、行全体のスレッドローカルコピーを作成するよりも複雑です。 StringBuilderとログ行を一度にWriterのようなクラスに記録します。

5
Peter Lawrey

StringBufferは、シングルスレッドアプリケーションでは間違っていませんStringBuilderと同じように機能します。

唯一の違いは、すべての同期メソッドを持つことによって追加される小さなオーバーヘッドです。これは、シングルスレッドアプリケーションでは利点がありません。

私の意見では、mainStringBuilderが導入された理由は、コンパイラがStringBuffer(そして今はStringBuilderString連結を含むコードをコンパイルする場合:その場合、同期は決して必要ではなく、それらすべての場所を同期されていないStringBuilderに置き換えることができます。パフォーマンスがわずかに向上します。

3
Joachim Sauer

StringBuilderはメソッドが同期されていないため、パフォーマンスが向上します。

したがって、文字列を同時に作成する必要がない場合(とにかく、これはかなり非典型的なシナリオです)、不要な同期オーバーヘッドを「支払う」必要はありません。

2
Andreas_D

これはあなたを助けます、Be Straight BuilderはBufferよりも速いです、

public class ConcatPerf {
        private static final int ITERATIONS = 100000;
        private static final int BUFFSIZE = 16;

        private void concatStrAdd() {
            System.out.print("concatStrAdd   -> ");
            long startTime = System.currentTimeMillis();
            String concat = new String("");
            for (int i = 0; i < ITERATIONS; i++) {
                concat += i % 10;
            }
            //System.out.println("Content: " + concat);
            long endTime = System.currentTimeMillis();
            System.out.print("length: " + concat.length());
            System.out.println(" time: " + (endTime - startTime));
        }

        private void concatStrBuff() {
            System.out.print("concatStrBuff  -> ");
            long startTime = System.currentTimeMillis();
            StringBuffer concat = new StringBuffer(BUFFSIZE);
            for (int i = 0; i < ITERATIONS; i++) {
                concat.append(i % 10);
            }
            long endTime = System.currentTimeMillis();
            //System.out.println("Content: " + concat);
            System.out.print("length: " + concat.length());
            System.out.println(" time: " + (endTime - startTime));
        }

        private void concatStrBuild() {
            System.out.print("concatStrBuild -> ");
            long startTime = System.currentTimeMillis();
            StringBuilder concat = new StringBuilder(BUFFSIZE);
            for (int i = 0; i < ITERATIONS; i++) {
                concat.append(i % 10);
            }
            long endTime = System.currentTimeMillis();
           // System.out.println("Content: " + concat);
            System.out.print("length: " + concat.length());
            System.out.println(" time: " + (endTime - startTime));
        }

        public static void main(String[] args) {
            ConcatPerf st = new ConcatPerf();
            System.out.println("Iterations: " + ITERATIONS);
            System.out.println("Buffer    : " + BUFFSIZE);

            st.concatStrBuff();
            st.concatStrBuild();
            st.concatStrAdd();
        }
    }

Output  

    run:
    Iterations: 100000
    Buffer    : 16
    concatStrBuff  -> length: 100000 time: 11
    concatStrBuild -> length: 100000 time: 4
    concatStrAdd   -> 
0
MyStack

オブジェクトを同期するには莫大なコストがかかります。プログラムをスタンドアロンエンティティと見なさないでください。概念を読んで、質問の詳細で述べたような小さなプログラムに適用する場合は問題ありません。システムを拡張するときに問題が発生します。その場合、シングルスレッドプログラムは他のいくつかのメソッド/プログラム/エンティティに依存している可能性があるため、同期されたオブジェクトはパフォーマンスの点で深刻なプログラミングの複雑さを引き起こす可能性があります。したがって、オブジェクトを同期する必要がないと確信している場合は、StringBuilderを使用する必要があります。これは優れたプログラミング手法です。最後に、スケーラブルで高性能なシステムを作成するためのプログラミングを学びたいので、それを行う必要があります。

0
Nikhil Arora

マニッシュ、StringBufferインスタンスで動作しているスレッドは1つだけですが、そのメソッドのいずれかが呼び出されるたびに、StringBufferインスタンスのモニターロックを取得および解放する際にオーバーヘッドが発生します。したがって、StringBuilderはシングルスレッド環境での推奨される選択です。

0
Praveen