threadlocal存连接对象的目的_终于懂了ThreadLocal,不再害怕面试官问了
ThreadLocal解析
synchronized和ThreadLocal的區別:
synchronized:以時間換空間,只提供一份變量,讓不同的線程排隊訪問,失去了并發性,降低了程序效率,著重對各線程之間訪問資源的同步性
ThreadLocal:以空間換時間,每個線程都提供一份變量副本,每個線程的數據是隔離的,提高了并發性
ThreadLocal使用場景:數據庫連接、Session管理
ThreadLocal的數據結構:
Mapnew ThreadLocal(),T>> map=new HashMap<>();
方便理解,源碼中并沒有這個map
set()方法:
getMap():
createMap():
Ok現在我們走一遍程序流程:1.現在有一個ThreadLocal實例對象->ThreadLocalconn_tl = new ThreadLocal()
調用conn_tl.set()方法,獲取當前執行的線程,根據當前線程獲取一個ThreadLocalMap實例對象threadLocals,threadLocals里面存 conn_tl和value
ThreadLocalMap是一個定義在ThreadLocal中的靜態內部類:
static class ThreadLocalMap {
static class Entry extends WeakReference> {
Object value;
Entry(ThreadLocal> k, Object v) {
super(k);//由于Entry繼承了WeakReference,所以這里以一個弱引用指向ThreadLcoal對象
value = v;
}
}
為什么ThreadLocalMap會是ThreadLocal的靜態內部類:ThreadLocalMap是由ThreadLocal創建管理的,只被ThreadLocal所使用
靜態內部類的作用:1)首先,用內部類是因為內部類與所在外部類有一定的關系,往往只有該外部類調用此內部類。所以沒有必要專門用一個Java文件存 放這個類。
2)靜態都是用來修飾類的內部成員的。比如靜態方法,靜態成員變量,靜態常量。它唯一的作用就是隨著類的加載(而不是隨著對象的產生)而產生,以致可以用類名+靜態成員名直接獲得。
這樣靜態內部類就可以理解了,因為這個類沒有必要單獨存放一個文件,它一般來說只被所在外部類使用。并且它可以直接被用外部類名+內部類名獲得。
為什么Entry中的key是弱引用:
這里的key是ThreadLocalconn_tl = new ThreadLocal()中的conn_tl。在外部他是一個強引用,在Entry中key是弱引用。也就是有兩個引用指向ThreadLocal實例對象
當外部方法執行完畢,棧幀銷毀強引用tl也就也就銷毀了,但此時線程的ThreadLocalMap里某個entry的 k 引用還指向這個對象。若這個k 引用是強引用,就會導致k指向的ThreadLocal對象及v指向的對象不能被gc回收,造成內存泄漏,但是弱引用就不會有這個問題(弱引用及強引用等這里不說了)。使用弱引用,就可以使ThreadLocal對象在方法執行完畢后順利被回收,而且在entry的k引用為null后,再調用get,set或remove方法時,就會嘗試刪除key為null的entry,可以釋放value對象所占用的內存。
概括說就是:在方法中新建一個ThreadLocal對象,就有一個強引用指向它,在調用set()后,線程的ThreadLocalMap對象里的Entry對象又有一個引用 k 指向它。如果后面這個引用 k 是強引用就會使方法執行完,棧幀中的強引用銷毀了,對象還不能回收,造成嚴重的內存泄露。
弱引用的好處:當一個對象僅僅被weak reference指向, 而沒有任何其他strong reference指向的時候, 如果GC運行, 那么這個對象就會被回收。如果存在強引用同時與之關聯,則進行垃圾回收時也不會回收該對象。
總結
以上是生活随笔為你收集整理的threadlocal存连接对象的目的_终于懂了ThreadLocal,不再害怕面试官问了的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html 图片position,【图解C
- 下一篇: python对角线图_python对角线