私は現在、メソッドインターセプタを使用してアスペクトとして実装しているイベント/アクティビティログシステムに取り組んでいます。現時点では、システム/フレームワークは各メソッドが1つのアクティビティであるとみなしますが、アクティビティが複数のメソッド呼び出しにまたがるように、このメソッドを拡張したいと考えています。これを行うためには、関連するすべてのメソッド呼び出しにいくつかのコンテキストを提供することによって心に浮かぶ最初のアプローチがあります。しかし、すべてのメソッド呼び出しが(Log4JのMDC/NDCのような)単一のスレッドのコンテキスト内にある場合、これを行う方法しかわかりません。複数のスレッドにコンテキストを提供する方法はありますか(おそらく、コードはマルチスレッドを意識することなく)?Java - 複数のスレッドのログ記録コンテキストを作成する
答えて
私は自分のコードでうまくいくと思います。これは、関連するすべてのスレッドが親/ルートスレッドから生成されていることを前提としています(これは安全な前提です)。
クラスThreadLocal?このようなsemsは、実際にはTLSのための有効かつ共鳴的な使用であるかもしれない - 既に存在するコードにコテキストを加える。
実際これが私が使用する予定です。私はそれがまだマルチスレッドでうまくいくかどうか分かりません。 –
ThreadLocalはマルチスレッドの問題を解決することです(私の答えでは、ContextManagerは通常ThreadLocalを内部で実装しています)。考えなければならない主な問題は、コンテキストコンテンツを別のスレッドに運ぶ方法です。あなたのアプリをマルチスレッドにする方法はたくさんあることを覚えておいてください。毎回新しいスレッドを生成するのが通常最悪の方法です。どのようにマルチスレッドを実行しているかは、コンテキストを伝播する方法に確実に影響します。 –
"ロギング"については考えないでください。それはもっと根本的なものになります。複数のスレッドが同じコンテキストで扱うアクションを実行するには、どのスレッドがどのコンテキストに対応しているかを認識させるためにどのように伝播していますか?
これに答えることができれば、このコンテキストはMDC/NDCに記録するために必要なものです(おそらくコンテキスト全体ではなく、そのコンテキストの重要な情報です)。
アプリケーションがそのような情報を持っていない場合、誰でもあなたのためにそれを判断する方法はありません。
編集:私はuのあなたが設定を行うことができる方法についていくつかのアイデアを与えるかもしれ
。それはさらにそれを強化するためにAOPを使用することが適切であるかどうか、それはあなたのさらなる研究だ:)
// Assume I have a ContextManager which Context is stored in thread local:
abstract class ContextAwaredJob implements Runnable {
public ContextAwaredJob() {
this.context = ContextManager.getCurrentContext();
}
public void run() {
ContextManager.setCurrentContext(this.context);
doRun();
}
protected abstract void doRun();
}
あなたは新しい「ジョブ」は、この親クラスを拡張するために起こっている、とあなたがすることによってこれを実行している場合、コンテキストが自動的に設定されます別のスレッド。 (もちろん、デザインはかなり洗練されていますが、何が起こっているのかについての基本的な考え方はあります)
+1、絶対に。何とかその文脈を設定しなければなりません。 –
私はこれを正しく理解しているかわかりません。とにかく、このアプローチはアスペクト指向であるため、ContextManagerなど、コンテキストを把握するためのコンポーネントがバックグラウンドに存在します。どのようにメソッドが実行されても、元の実行スタックと同じスレッドか異なるスレッドかに関わらず、コンテキストは同じままであるように、構造化したいと思います。私がここで意味を成しているかどうかは分かりません。私はマルチスレッドの経験があまりありません(少なくとも直接的ではありません)。 –
問題は「元の実行スタックと同じスレッドか異なるスレッドかにかかわらず」です。通常、同じスタック内のメソッド呼び出しスタックは、同じコンテキストの下にあると合理的に考えることができます。しかし、実行する他のスレッドがある場合、u以外の誰も正しいコンテキストを知っていません。たとえば、スレッドプールのジョブを実行するジョブディスパッチャがあります。「コンテキスト」をユーザーセッションにしたい場合は、新しいスレッドのコンテキストを設定する必要があります。私はそのような場合に特定のfwセットアップの特定のコンテキストを信じていますが、あなただけが本当に望んでいることを知っています –
それはそれほど単純ではありません。 1つの潜在的な問題は次のようなものです:http://stackoverflow.com/questions/7296623/inheritablethreadlocal-and-thread-pools。だからこそ私はいつもそのような文脈を明示的に設定する必要があることを強調している。 –
私の唯一の問題は、私が現在取り組んでいるアプリケーションが現在スレッドを明示的に生成していないということです。一部のサードパーティ製のAPIはバックグラウンドで実行している可能性がありますが、これまで私が知っているAPIはありません。私は、現時点でInheritableThreadLocalが提供しているマルチスレッドコンテキストのサポートが限られていても、それにはかなり満足しています。私はあなたの提案を書き留めておきますので、将来このような問題に遭遇したときに使用することができます。ありがとう。 –