1

インスタンス変数としてThreadLocalを持つシングルトンを構築しています。このシングルトンには、複数のスレッドからアクセスできるメソッドがあり、遅延インスタンス化されます。今、私はこのようなことを考えています:

static final ThreadLocal<HashMap> bindingContext = new ThreadLocal<HashMap>();

しかし、それが良いアイデアかどうかはわかりません。使用しているので、インスタンス変数にするオプションもあります(シングルトンで述べたように)。

したがって、問題は、そのクラス変数を初期化するのに最適な場所はどこですか、それともクラス変数にする必要があるかということです。

4

3 に答える 3

4

静的初期化子がスレッドセーフな方法で実行されることが保証されています。JLSはこれについて具体的に言及しています。

Javaプログラミング言語はマルチスレッドであるため、他のスレッドが同じクラスまたはインターフェースを同時に初期化しようとしている可能性があるため、クラスまたはインターフェースの初期化には注意深い同期が必要です。クラスまたはインターフェースの初期化が、そのクラスまたはインターフェースの初期化の一部として再帰的に要求される可能性もあります。たとえば、クラスAの変数初期化子は、無関係のクラスBのメソッドを呼び出し、次にクラスAのメソッドを呼び出す場合があります。Java仮想マシンの実装は、次の手順。


これについて詳しく説明しているJLSの セクション12.4.2を参照してください。

編集:そしてあなたがしようとしていることは完全に大丈夫です。ThreadLocalのjavadocsから:

ThreadLocalインスタンスは通常、状態をスレッド(たとえば、ユーザーIDまたはトランザクションID)に関連付けたいクラスのプライベート静的フィールドです。

于 2012-06-12T18:37:26.380 に答える
1

静的メンバーは、新しいThreadLocalが作成されることを保証しますが、そのThreadLocalの初期値は、新しいスレッドごとにnullになります。initialValue()メソッドをオーバーライドすることで、スレッド固有の初期値を簡単に提供できます。これを行う1つの方法は、匿名の内部クラスEGを使用することです。

static final ThreadLocal<HashMap> bindingContext = new ThreadLocal<HashMap>() {
    @Override protected HashMap initialValue() {return new HashMap();}
    };
于 2014-03-11T15:16:45.843 に答える
1

Lamdaを使用すると、次のように記述できます。

private ThreadLocal<Map<String,String>> bindingContext = ThreadLocal.withInitial(HashMap::new);
于 2019-06-10T04:09:04.887 に答える