ThreadLocalのはThreadLocalの変数は、現在のスレッドのみのアクセスで作成することができますスレッドローカル変数を格納するために使用することができ、他のスレッドが変更することはできません。読み書きするスレッド間で互いに分離。
まず、原理は解決します
。1、クラスThreadLocalのThreadLocalMapサブクラスの存在下で、及び同様のHashMapを達成するため、ThreadLocalMap結合のThreadLocalの弱参照です。
弱参照:ThreadLocalのオブジェクトへのすべての強い参照がない場合には、弱参照は、直接次のGCで回収されます。
図の以下のサブクラスを達成ThreadLocalMap。
図2に示すように、ソースThreadLocalのクラスセット法、ソースコードを参照してください。
1)現在のスレッドを得ました。
2)ThreadLocal.ThreadLocalMap threadLocals変数現在のスレッドを取得し、変数は、スレッドクラスのメンバ変数です。
3)可変ThreadLocalMapスレッドが空、直接割り当てない場合。
4)変数が空ThreadLocalMapスレッドである場合、新しいThreadLocalMap(オブジェクトを初期化するために、この、firstValue)ThreadLocalMap、及び対応するThreadLocalのインスタンスコンストラクタを通過する電流を呼び出します。
3、ないソースコードで、ソースにThreadLocalクラスのgetメソッド、比較的単純なロジックを参照してください。
1)現在のスレッドを取得します。
2)スレッドに対応するThreadLocalMap可変電流を得ます。
3)エントリがThreadLocalMapによって現在ThreadLocalのインスタンスに対応する取得し、対応する値を取得します。
図4は、スレッドがそれぞれのThreadLocalは影響を受けません達成するためにどのように、より多くのThreadLocal変数を持っている場合、状況はお互いをカバーするためには表示されません。
民間最終int型threadLocalHashCode = nextHashCode();
プライベート静的のAtomicInteger nextHashCode =新しいのAtomicInteger();
プライベート静的最終int型のHASH_INCREMENT = 0x61c88647。
プライベート静的int型nextHashCode(){
nextHashCode.getAndAdd(HASH_INCREMENT)を返します。
}
私たちは、ThreadLocalの内部には、一定の静ハッシュコード値を維持し、見ることができ、それぞれのThreadLocalを一意にハッシュコード値に相当し、マップが操作を取得/設定されている場合、状況は対象外となりますことを確認してください。
第二に、ThreadLocalの使用に注意してください
ソースによって実装するためにThreadLocalソースコードを理解し、ちょうど表面に滞在することはできません、我々は、使用するために注意を払う必要がある場合、ソースコードは非常に達成し、なぜに行く必要があります。
日々の開発では、以下の質問が必要です。
1、ThreadLocalMapはなぜThreadLocalの弱い参照を維持しますか?どのようなメモリリークのルート理由は?
参照関係は以下の通り:
それは前提に注意する必要があります。ライフサイクルのスレッドが非常に長い場合。
まず第一に、私たちは強い参照を保持する場合は、無理にする必要があり、それはメモリリークが発生します。キーが風で消えてしまいますThreadLocalMap、GCを回復することがTHREADLOCAL弱参照を保持し、null値がnullではない、それはいくつかのメモリリークの原因となりますため、主要な場面がたくさんあるでしょう。
スレッドの終焉後まで、ThreadLocalMapスレッドが最終的に回復されます。
JVMは、この点で最適化された場合は、メソッドを削除、取得、セットを呼び出し、キーがnullのマップをクリーンアップします。
メモリリークの根本的な原因は、スレッド場合はすぐに死ぬので、スレッドがメモリリークが発生しないクリーンアップするThreadLocalMapます、ライフサイクルのスレッドが非常に長いです。
2、次の事項スレッドプール戦略を使用して。
スレッドプールポリシーの適用、いくつかのスレッドがタスクを繰り返します。実行のrunメソッドの終了前に、ThreadLocalのない、クリーンアップするために、異常動作を引き起こす可能性が表示されますのThreadLocalの値をカバーするような状況が発生します場合を想像してみてください。
所以,在线程池的策略下使用ThreadLocal,需要像lock进行加锁和解锁一样,finally里面对ThreadLocal进行remove。
3、子线程如何使用父线程的ThreadLocal变量?
可以使用InheritableThreadLocal。
通过看Thread的源码发现:
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
InheritableThreadLocal<T> extends ThreadLocal<T>
InheritableThreadLocal继承了ThreadLocal类,重写了getMap和createMap。操作的是线程的inheritableThreadLocals 变量。
再通过查看Thread的构造方法,可以发现,会对父线程的ThreadLocal变量进行复制,并将值赋给inheritableThreadLocals。
如有不对之处,欢迎指正!