2

こんにちは、私はこのようなクラス定義を持っています

public class JdbcInterceptor {
private static final JdbcInterceptor instance = new JdbcInterceptor();
private static ThreadLocal<Boolean> dontIntercept = new ThreadLocal<Boolean>();
     public static JdbcInterceptor getInstance() {
 return instance;
}
public void skipIntercept() {
 dontIntercept.set(true);
}
public boolean interrupt() {
boolean di = dontIntercept.get()!=null?dontIntercept.get().booleanValue():false;
if (di) {
        dontIntercept.set(false);
        }
return di;
}// end interrupt
}// end class

そして、私はこれを他のクラスで行います1

//class1 stuff
JdbcInterceptor.getInstance().skipIntercept();
if(JdbcInterceptor.getInstance().interrupt())
{ // class1 stuff happens
}

今、私はclass2でこれを行います

//class2 stuff
if(JdbcInterceptor.getInstance().interrupt())
{ // class2 stuff happens
}

dontIntercept ThreadLocal を設定したため、class1 が発生することはわかっています。私の疑問は、クラス2のものが起こるかどうかです? 私の論理では、JdbcInterceptor のインスタンスは 1 つしかないため、interrupt() へのすべての呼び出しで同じ状態を使用できるはずです。しかし、ThreadLocals はスレッドごとにローカルであると言われました。ここでいくつかの競合が見られます。これについて私を助けてください。

4

1 に答える 1

4

あなたの質問はあまり明確ではありません。

しかし、ThreadLocals はスレッドごとにローカルであると言われました。ここでいくつかの競合が見られます。

正解です。競合はありません。で格納される値オブジェクトThreadLocalは、各スレッドに固有です。実際にはThreadオブジェクトと共に内部的に保存されるため、スレッドが終了すると、他のスレッドからそれらへの他の参照がない限り、すべてのスレッド ローカル値も削除され、ガベージ コレクションに使用できます。

両方のクラスが同じスレッドで実行される場合、呼び出し間でスレッド ローカルの値を変更しない限り、両方の結果が同じになります。別のスレッドが class2 を実行する場合、2 つの値は異なります (例による)。

おそらく、時間とクラス/メソッドのストレージとコードで発生するスレッドの実行を混同しています。この 2 つは大きく異なります。1 つのスレッドですべてのメソッドを実行することも、1 つのクラスで同じメソッドを実行する多数のスレッドを持つこともできます。コード内のスレッドを「見る」ことはできません。他の写真がなければ、それらを想像する必要があります-それには注意深い視覚化が必要です.

ThreadLocal次のように、イニシャライザを使用して、コードを少し明確にすることができます。

private static ThreadLocal<Boolean> dontIntercept = new ThreadLocal<Boolean>() {

    @Override
    protected Boolean initialValue() {
        return Boolean.FALSE;
    }

};

null次に、スレッドローカルを使用する場合、次のように、それが であるかどうかを確認する必要はありません。

public boolean interrupt() {
    return dontIntercept.get().booleanValue();
}// end interrupt

以下は、これが 2 つ以上のスレッドでどのように実行されるかを示す試みです。

 Thread1 start---class1(skip=false)-+-skip(true)---+class1(true)--+class2(true)----+-end
                    |               |              |              |                |
                    Thread2 start---+-class1(false)+--------------+class2(false)---+-class1(false)---end

classN(val) を表示すると、値はスキップ スレッド ローカル変数がその時点で設定されている値です。

より具体的に質問に答えるには、この例で: class1 と class2 のコードは両方とも、thread1 によって実行されるとスキップされます。thread2 によって実行されると、それらはスキップされません。

と呼ばれる別の種類のスレッド ローカルがあることに注意してくださいInheritableThreadLocal。これは、スレッドが 2 番目のスレッドを開始した時点でThread1にあった値をThread2が継承するため、私の例では動作が異なります。

編集class1 のコードで常にスキップ値を true に設定すると、動作が少し変わります。スレッドが最初に class1 を実行し、次に class2 を実行すると、スキップはtrue両方に対して行われます。スレッドが最初に class2 を実行し、次に class1 を実行する場合false、前者はスキップされ、後者はスキップされますtrue。スキップを に戻す方法があることを示していませんfalse

編集質問を読み直してください。実際、すべてのスレッドでまったく同じ状態が必要な場合は、ThreadLocal. 通常の変数を使用して、それをマークするかvolatile、同期で保護します。

于 2010-01-29T08:49:47.233 に答える