併發編程之ThreadLocal分析一

知識點:

  1. 神奇的hashcode , 0x61c88647
  2. 弱引用 WeakReference 拓展java引用相關
  3. 關鍵點 ThreadLocalMap
  4. AtomicInteger

應用案例:

  1. spring RequestContextHolder
  2. zuul RequestContext
  3. guava Dispatcher
  4. tomcat ApplicationContext

 

1.神奇的hashcode   0x61c88647

0x61c88647是什麼?轉化爲十進制是1640531527。2654435769轉換成int類型就是-1640531527。2654435769等於(根號5-1)/2乘以2的32次方。(根號5-1)/2是什麼?是黃金分割數,近似爲0.618。也就是說0x61c88647理解爲一個黃金分割數乘以2的32次方。有什麼好處?它可以神奇的保證nextHashCode生成的哈希值,均勻的分佈在2的冪次方上,且小於2的32次方看以下的舉例

import java.util.concurrent.atomic.AtomicInteger;

/**
 * <h3>類的基本描述</h3>
 *
 * @author hcmony
 * @since V1.0.0, 2020/5/9 09:38
 */
public class ThreadLocalTest {

    private final int threadLocalHashCode = nextHashCode();

    /**
     * The next hash code to be given out. Updated atomically. Starts at
     * zero.
     */
    private static AtomicInteger nextHashCode =
            new AtomicInteger();

    /**
     * The difference between successively generated hash codes - turns
     * implicit sequential thread-local IDs into near-optimally spread
     * multiplicative hash values for power-of-two-sized tables.
     */
    private static final int HASH_INCREMENT = 0x61c88647;

    /**
     * Returns the next hash code.
     */
    private static int nextHashCode() {
        return nextHashCode.getAndAdd(HASH_INCREMENT);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 16; i++) {
            System.out.print(i+"->"+(nextHashCode()&15)+",");
        }
    }
}

結果:0->0,1->7,2->14,3->5,4->12,5->3,6->10,7->1,8->8,9->15,10->6,11->13,12->4,13->11,14->2,15->9

2.弱引用 WeakReference 拓展java引用相關

 

  • 強引用(StrongReference)

強引用是使用最普遍的引用。如果一個對象具有強引用,那垃圾回收器絕不會回收它。當內存空間不足,Java虛擬機寧願拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具有強引用的對象來解決內存不足的問題,如下圖當o=null時纔會被GC回收,或者程序執行完成,具體看JVM垃圾回收中可達性分析算法。

Object o = new Object() o = null;

 

  • 軟引用(SoftReference)

如果一個對象只具有軟引用,則內存空間足夠,垃圾回收器就不會回收它;如果內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就可以被程序使用。軟引用可用來實現內存敏感的高速緩存。軟引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用的對象被垃圾回收器回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。

Object softReferenceO = new Object(); SoftReference<Object> softReference = new SoftReference<>(softReferenceO);

 

  • 弱引用(WeakReference)

弱引用與軟引用的區別在於:只具有弱引用的對象擁有更短暫的生命週期。在垃圾回收器線程掃描它所管轄的內存區域的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。不過,由於垃圾回收器是一個優先級很低的線程,因此不一定會很快發現那些只具有弱引用的對象。弱引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關聯的引用隊列中。

Object weakReferenceO = new Object(); WeakReference<Object> weakReference = new WeakReference<>(weakReferenceO);

 

  • 虛引用(PhantomReference)

“虛引用”顧名思義,就是形同虛設,與其他幾種引用都不同,虛引用並不會決定對象的生命週期。如果一個對象僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。虛引用主要用來跟蹤對象被垃圾回收器回收的活動。虛引用與軟引用和弱引用的一個區別在於:虛引用必須和引用隊列 (ReferenceQueue)聯合使用。當垃圾回收器準備回收一個對象時,如果發現它還有虛引用,就會在回收對象的內存之前,把這個虛引用加入到與之 關聯的引用隊列中。

 

3.ThreadLocalMap ThreadLocal最重要的內部類

  • 理解ThreadLocal 要理解它與Thread、ThreadLocalMap 的關係,如下圖:

每個線程都有一個LocalThreadMap,LocalThreadMap初始化時有16個卡槽,每個卡槽放着一個Entry,對應的Key是ThreadLocal,這裏的Key就是上面說到繼承了弱引用類型,在我們使用remove方法時候就會用到。Value爲Object 類型,也就是我們要放入的對象。具體ThreadLocalMap下一章詳細分析。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章