16

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

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

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

4

8 に答える 8

27

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

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

だからStringBuilder

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

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

于 2011-05-30T09:08:14.663 に答える
7

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

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

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

http://download.oracle.com/javase/6/docs/api/java/lang/StringBuffer.html

于 2011-05-30T09:04:54.187 に答える
5

複数のスレッドで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などのクラスに作成します。

于 2011-05-30T11:26:04.533 に答える
3

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

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

私の意見では、コンパイラが連結を含むコードをコンパイルするときに(そして今は)使用することが主な理由です。そのような場合、同期は必要なく、それらの場所をすべて非同期に置き換えると、パフォーマンスがわずかに向上します。 。StringBuilderStringBufferStringBuilderStringStringBuilder

于 2011-05-30T09:09:34.640 に答える
2

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

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

于 2011-05-30T09:06:33.113 に答える
0

これは皆さんに役立ちます。BeStraightBuilderは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   -> 
于 2013-02-17T17:44:49.570 に答える
0

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

于 2013-06-05T09:58:11.667 に答える
0

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

于 2017-06-10T18:13:47.483 に答える