2011-09-04 14 views
7

解決策があるとは思えない問題がありますが、とにかくここで試してみます。私のアプリケーションはスレッドプールを使用し、このプール内のいくつかのスレッドは継承可能なスレッドローカル変数を持っています。 ThreadPoolExecutorクラスを拡張して、スレッドの実行が完了したときに、スレッドローカル変数(afterExecuteコールバックメソッド内)を実質的にクリアしました。InheritableThreadLocalとスレッドプール

InheritableThreadLocal変数がある場合、親スレッドからThreadLocal変数の値を取得するためにスレッドが初期化されたときに、childValue()メソッドが呼び出されることを理解しています。しかし、私の場合は、スレッドが次回使用されたとき(一度使用された後)、InheritableThreadLocal変数の値はnullです(beforeExecuteで以前クリアされていたためです)。スレッドの作成時にInheritableThreadLocalのchildValueメソッドが本質的にシミュレーションできるように、beforeExecuteの親スレッドのスレッドローカル変数にアクセスする方法はありますか?

+1

結果ですか?子スレッドが最初に作成されて以来、異なる親スレッドからの次の実行時に必要な値は変更されていますか? –

+0

@Bert - これが理由です。基本的には、スレッドIDをスレッドローカル変数に格納しています。この変数は、子スレッドの複数回の使用を変更します。 – neesh

答えて

4

これは、スレッドローカルの "継承可能な"味の悪いユースケースです。

私の助言は、普通のTheadLocalを使用し、初期化を明示的に行うことです。例えば親スレッドからの初期値を子スレッドにパラメータとして渡します。

(私は、スレッドローカルの子スレッドの初期化を強制することを提案していますが、開始するとすぐに値をフェッチしますが、これは競合状態になる可能性があります。子スレッドから親スレッドのスレッドローカル変数の値にアクセスする方法がある場合は、プールの子スレッドが実行を開始する前に。)


私は私が求めていますどのような思いです。

これを行う方法はありません。

他のコメントから判断して、通常の意味では "親"と "子"を意味するのではないでしょうか...親スレッドが子スレッドを作成するところです。

しかし、ここに考えがあります。スレッド間で変数を共有するのではなく、固定値(リクエストIDなど)を共有し、その変数を共有のMapのキーとして使用します。共有変数としてMapエントリを使用します。

+1

お返事ありがとうございます。私は子スレッドのスレッドローカルを強制的に初期化する方法が不思議です。私は、親スレッドのスレッドローカル変数の値に子スレッドからアクセスする方法があるかどうか聞いています。 – neesh

+0

残念なことに、この回答は問題を開いたままにしています。スレッドローカルからスレッドへの転送方法その子が他の子の子であれば、InheritableThreadLocalsはうまく機能しますが、スレッドプールの場合はどうしますか? – Gregor

+0

なぜあなたは答えをdownvoteでしたか?良い解決策が存在しないと答えた人は、あなたがその事実を気に入らないという理由だけで、あまりにも失礼です。確かに、私はあなたを助けることを奨励していません! –

0

runnableのコンストラクタは呼び出し元のスレッドで実行されますが、runメソッドは子スレッドで実行されます。このファクトを使用して、親から子スレッドに情報を転送できます。参照:

public class ThreadlocalApplication { 
static public ThreadLocal<String> tenantId = new ThreadLocal<>(); 

public static void main(String[] args) throws ExecutionException, InterruptedException { 
    ExecutorService executor = Executors.newCachedThreadPool(); 
    System.out.println(Thread.currentThread().getName()); 
    ThreadlocalApplication.tenantId.set("4711"); 
    executor.submit(new AsyncTask()).get(); 
    executor.shutdown(); 
} 

static class AsyncTask implements Runnable { 
    private String _tenantId; 

    public AsyncTask() { 
     System.out.println(Thread.currentThread().getName()); 
     _tenantId = ThreadlocalApplication.tenantId.get(); 
    } 

    @Override 
    public void run() { 
     ThreadlocalApplication.tenantId.set(_tenantId); 
     System.out.println(Thread.currentThread().getName()); 
     System.out.println(ThreadlocalApplication.tenantId.get()); 
    } 
} 
} 

そして、あなたは後でそれが必要な場合は、子スレッドのスレッドローカル値をクリアしているなぜこれが

main 
main 
pool-1-thread-1 
4711 
関連する問題