7

高く評価されている本JCIPは、ThreadLocalの使用法について次のように述べています。

スレッド制限プロパティをグローバル変数を使用するためのライセンスとして、または「非表示」メソッド引数を作成する手段として扱うことにより、ThreadLocalを悪用するのは簡単です。スレッドローカル変数は、再利用性を損ない、クラス間に隠れた結合を導入する可能性があるため、注意して使用する必要があります。

スレッドローカル変数が再利用性を低下させ、クラス間に隠れた結合を導入する可能性があるとはどういう意味ですか?

4

2 に答える 2

11

それらは、グローバル変数が行うのとほぼ同じ方法で再利用性を低下させます: メソッドの計算が、メソッドの外部にあるがパラメータとして渡されない状態 (たとえば、クラス フィールド) に依存する場合、メソッドは再利用性が低くなります。それが存在するオブジェクト/クラスの状態に(またはさらに悪いことに、完全に別のクラスに)。

編集:わかりました、これはより明確にするための例です。ThreadLocal質問のためだけに使用しましたが、一般的にグローバル変数に適用されます。最初の N 個の整数の合計を複数のスレッドで並列に計算したいとします。これを行う最善の方法は、各スレッドのローカル合計を計算し、最後にそれらを合計することです。何らかの理由でcall、それぞれのメソッドが、異なるクラスでグローバル (静的) 変数として定義されている変数をTask使用することにしました。ThreadLocal sum

class Foo {
    public static ThreadLocal<Long> localSum = new ThreadLocal<Long>() {
        public Long initialValue() {
            return new Long(0);         
        }
    };
}

class Task implements Callable<Long> {

    private int start = 0;
    private int end = 0;    

    public Task(int start, int end) {
        this.start = start;
        this.end = end;
    }

    public Long call() {
        for(int i = start; i < end; i++) {
            Foo.localSum.set(Foo.localSum.get() + i);
        }
        return Foo.localSum.get();
    }
}

コードは正しく機能し、グローバル合計の期待値を返しますが、クラスTaskとそのcallメソッドがクラスに厳密に結合されていることに気付きFooます。Taskクラスを別のプロジェクトで再利用したい場合は、Fooクラスも移動する必要があります。そうしないと、コードがコンパイルされません。

これは意図的に複雑な単純な例ですが、「隠された」グローバル変数の危険性を見ることができます。また、コードを読んでいる他の誰かがクラスFooを検索し、定義が何であるかを確認する必要があるため、可読性にも影響しFoo.localSumます。クラスはできるだけ自己完結型に保つ必要があります。

于 2012-07-01T15:51:08.287 に答える
3

Aはスレッドごとに宣言されます - 通常、フィールドはそのクラスのオブジェクトごとに宣言されます - これから始まる -が誤用されるThreadLocalと、うまくいかないことがたくさんあります。ThreadLocal

スレッドが複数のオブジェクト (単一クラスまたは複数クラスのいずれか) を通過する場合、ThreadLocalこのスレッドで使用される は、これらすべてのインスタンスで同じインスタンスです。これは、BGが話しているカップリングです。カップリングが発生すると、再利用が難しくなり、エラーが発生しやすくなります。

于 2012-07-01T15:52:31.047 に答える