2009-03-10 23 views
13

複数の文字列から文字列を構築していますが、StringBufferまたはStringBuilderのいずれかを使用します。 Java 5つのドキュメントから、私は可能な場合StringBuilderStringBuilderJava StringBuilderとスレッドセーフ

インスタンスが複数のスレッドで安全に使用できないことを警告し、好ましいことがわかります。

この文から、複数のスレッドで単一のStringBuilderインスタンスを共有するべきではないことを理解しました。しかしこの場合について:

//Is this safe? 
//foo() is called simultaneously by multiple threads 
String foo(String a, String b) { 
    return new StringBuilder(a).append(b).toString(); 
} 
ここ

同時にStringBuilderクラスを使用して、同時に機能では、複数のスレッドがあるかもしれません(例えば、静的変数の同時アクセス、もしあれば)、各スレッドはStringBuilderという独自の別個のインスタンスを持ちます。ドキュメントから、私はこれが複数のスレッドによって使用されるかどうかを決めることはできません。

+0

インスタンス変数には触れないので、foo()を静的メソッドにするといくらかのメリットがあるかもしれません。 – Kip

+0

@Kip:クラスに依存します。しかし、多型演算を実行し、そのメソッドを静的にすると、これが妨げられることがあります。 – OscarRyz

+0

String.concatを使用する方が高速ですが、これは単なる例にすぎません。 –

答えて

19

これは完璧です。ローカル変数は、インスタンス変数やクラス変数にアクセスしたり変更したりしない限り、スレッドの安全性に問題はありません。

11

はい、安全です。StringBuilderオブジェクトはローカルでのみ使用されるため(foo()を呼び出す各スレッドは独自のStringBuilderを生成します)。

はまた、あなたが投稿コードは、このことにより、生成されたバイトコードと実質的に同一であることに注意してください:

String foo(String a, String b) { 
    return a + b; 
} 
+0

バイトコードはどうやって見ますか? – OscarRyz

+0

@Oscar:javap -c

+0

も参照してください:http://stackoverflow.com/questions/272535/how-do-i-decompile-java-class-files – Kip

4

は、他の回答に同意します - ちょうどノート。

StringBufferが複数のスレッドで使用されていた場合は、1つの文字列が準ランダムな順序で構築されていることを意味するため、完全に壊れている可能性がありますStringBufferをスレッドセーフにします。

+0

それはStringBuilderの根拠です。ほとんどの場合、同期は必要ありませんでした。 – OscarRyz

+0

はい、なぜ、彼らは並列StringBuilderを作成するのではなく、単にStringBufferを書き直さなかったのだろうかと思います。非決定的な文字列を構築する、そのアプリケーションの下位互換性を維持するには? –

+1

マルチスレッドアプリケーションのメモリ内ロギングのためにStringBuilderを使用していたとしますか?なぜあなたがそれをやっているのか分かりません... – Kip

3

Javaが自動的にStringBuilderを選択するので、このコードが必要かどうかわかりません。パフォーマンスに問題がない場合は、+ bを押してください。パフォーマンスの必要性の場合

、それを試してみてください。

return new StringBuilder(
a.length() + b.length()).append(a).append(b).toString(); 

それは正しく、バッファのサイズと、それをリサイズし、途中で収集するごみの作成からVMを防ぐことができます。

6

あなたが持っているコードは安全です。

このコードはありません。

public class Foo 
{ 
    // safe 
    private final static StringBuilder builder; 

    public static void foo() 
    { 
     // safe 
     builder = new StringBuilder(); 
    } 

    public static void foo(final String a) 
    { 
     // unsafe 
     builder.append(a); 
    } 

    public synchronized void bar(final String a) 
    { 
     // safe 
     builder.append(a); 
    } 
} 

ローカルデータのみを使用するローカル変数は、スレッドセーフではありません。クラスまたはインスタンスのメソッド/変数レベルで表示されるデータを処理すると、スレッドセーフな問題のみが発生します。