ThreadLocalの使い方と原理に関するこの記事は、非常によく書かれています:
メモリリーク
テストコード:
public class Test {
public static ThreadLocal<String> test = new ThreadLocal<>();
public static void main(String[] args){
Test.test.set("test");
Test.test = null;
System.gc();
System.out.println("1");
}
}
ここでスレッドローカルの原理は簡単ですが、つまり、スレッドはThreadLocalMap変数を保持し、その後、毎回threadLocal.get()またはthreadLocal.set()、現在の郡のスレッドローカルを決定するために戻るスレッドローカル内部がない場合は、Entryデータ構造を作成し、このデータ構造Threadlocalオブジェクトは、WeakReferenceオブジェクトにラップされ、値が内部のEntry値フィールドに設定されます。GC 2011 がアクティブになると、まず WeakReference オブジェクトを null に設定し、オブジェクトをリサイクルします。
public static ThreadLocal<String> test = new ThreadLocal<>();
次に、デモを見ると、静的変数があり、test が最初に test に設定され、実際には強い参照である属性セットで、次に test = null に設定されるため、実際には、強い参照の関係は壊れ、ThreadLocalMap 内の Entry だけが残り、ThreadLocalMap への弱い参照にラップされます。スレッドプールオブジェクトを使用するには、この時間は、GCは、このThreadLocalからリサイクルされますが、スレッドオブジェクトのスレッドがリリースされていないため、Entryの配列内のEntryの内部のスレッドは、まだ値の内部に格納されている値も存在するなど、存在する実行する場合は、この時間は、スレッドがリサイクルされません。スレッドプールオブジェクトを使用する場合は、スレッドがリサイクルされませんが、ループ内でスレッドを使用し続ける場合は、それがリークされます。
個人的に、私はこの時間の回復は、インスタンスが弱い参照をパッケージ化し、それを参照するための強力な参照がないことを発見したGCRootsスキャン時間を行うことであると思います、その後、JVMは弱い参照をNULL値に設定し、同時にGCスレッドは彼を回復するために。
実用的な使用
プロジェクトでは、多くの場合、コンテキストコンテキストの役割を行うためにスレッドローカル変数を使用するようなPageHelper内部のページ番号などのページングページングパラメータかどうかを設定するスレッドローカル変数を設定するの使用であり、その後、Mybatisは、テイクアウト、およびクエリの内側にそれを傍受します。
Springのトランザクション管理は、Threadlocalの使用は、Connectionの接続を設定し、トランザクションの伝播メカニズムを達成するためにsetrollbackonly変数をロールバックする必要があるかどうかです。
私自身は、データのアクセス許可を実装するプロセスでも直接Threadlocalプラスmybatisインターセプターの方法を使用して、データのフィルタリングを実現するために元のSQLステートメントを変更することです。
threadlocal.remove()
実際には、我々は、メモリオーバーフローの問題のスレッドの再利用を避けるために、このメソッドはまた、ThreadLocalMapからNULL変数のキーを内部を削除するには、削除を達成するためにメソッドの使用に注意を払う必要があります。
public static final ThreadLocal<String> test = new ThreadLocal<>();
実際には、一般的な使用は、このような問題の使用は、変数の最終型に設定され、彼も弱い参照を削除されませんので、テスト= nullのようなステートメントを設定することはできませんので、コンパイラがオーバーされませんので、より多くのメソッドを削除する必要があります。