Java中Integer和ThreadLocal

來源:互聯網
上載者:User

標籤:clu   for迴圈   creat   size   執行個體   不為   conf   引入   相等   

一. Integer1.引子

在開始之前,我還是需要吐槽下自己,我是真的很菜!

  • 他問:**兩個Integer對象==比較是否相等?
  • 我答:對象==比較,是引用比較,不相等!
  • 他問:IntegerCache這個用來幹什嗎?
  • 我答:......,我不是很清楚!!!

從這裡可以看出,我是真的很水!!
基於這些原因還有其他的等等,我開始寫博文,開始寫踩過的坑!

2.IntegerCache

在介紹這個緩衝之前,先來認知下Integer。java中,int是基本的數實值型別,表示整型;Integer是其對象的表示,是int的封裝類。封裝類在Jdk1中就存在,但是為了更方便的使用Integer,在Java SE5中引入自動封裝和自動拆箱的機制,這裡不再贅述,可以移步至深入剖析Java中的裝箱和拆箱。
Java SE5可以說是java版本迭代過程中裡程碑版本。為了減少大量建立Integer的開銷、提高效能,採用享元模式,引入Integer執行個體緩衝,將-128至127範圍數值的Integer執行個體緩衝在記憶體中,這裡的緩衝就是使用Integer中的輔助性的私人IntegerCache靜態類實現。

先看下如何擷取緩衝的-128至127範圍的Integer執行個體,這裡的範圍可以通過JVM啟動參數修改,後面會講述

  • 可以通過使用靜態valueOf方法擷取 // api調用
  • 可以使用自動封裝機制擷取,如:Integer a = 100; // autoboxing

這裡基於Java SE8,再來看下IntegerCache的實現:

/** * Cache to support the object identity semantics of autoboxing for values between * -128 and 127 (inclusive) as required by JLS. * * The cache is initialized on first usage.  The size of the cache * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option. * During VM initialization, java.lang.Integer.IntegerCache.high property * may be set and saved in the private system properties in the * sun.misc.VM class. */private static class IntegerCache {    static final int low = -128;    static final int high;    static final Integer cache[];    static {        // high value may be configured by property        int h = 127;        String integerCacheHighPropValue =            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");        if (integerCacheHighPropValue != null) {            try {                int i = parseInt(integerCacheHighPropValue);                i = Math.max(i, 127);                // Maximum array size is Integer.MAX_VALUE                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);            } catch( NumberFormatException nfe) {                // If the property cannot be parsed into an int, ignore it.            }        }        high = h;        cache = new Integer[(high - low) + 1];        int j = low;        for(int k = 0; k < cache.length; k++)            cache[k] = new Integer(j++);        // range [-128, 127] must be interned (JLS7 5.1.7)        assert IntegerCache.high >= 127;    }    private IntegerCache() {}}

從java docs中可以看出,該類是為了支援對-128至127範圍數值自動封裝的執行個體進行緩衝。
在第一次使用時緩衝被初始化,緩衝的大小可以通過JVM參數-XX:AutoBoxCacheMax=size控制,IntegerCache的high可以通過在JVM啟動時設定系統屬性變數java.lang.Integer.IntegerCache.high,以達到更強的靈活性。IntegerCache在執行類構造器初始化時,執行靜態語句塊,利用for迴圈從low開始不斷自加加,然後放入cache數組中。
選擇-128至127範圍,是因為這個範圍內的數值使用更普遍!

介紹到這裡,相信已經不難看出我的回答是多麼搞笑,我坐井觀天的還以為自己是正確的!
說到這裡,我又有些感慨了,昨晚看了集火影,剛好是自來也和佩恩的對話,佩恩對曾經的師傅自來也的一席話,雖然是偏執的,但是無可否認的確是對的。
佩恩把自己稱為神,將自來也視作為凡人,說凡人的認知具有局限性,活在狹小的空間內自認為自己認識都是對的,殊不知從神的角度考慮,凡人的那些認知都是錯誤和愚蠢的。
這裡旨在單純思考佩恩這些話在我們現實生活中的含義:的確,在我們認知有限的時候,以為Integer兩個對象==比較,應該是不等的,殊不知因為技術掌握有限。

跑題了,引入一段故事,主要是想銘刻下,吸取教訓:不要把事物看做是理所當然,要多多思考其本質和原理;不要妄下結論,小心求證!

不僅是Integer,Short、Byte、Long、Char都具有相應的Cache。但是Byte、Short、Long的Cache有固定範圍:-128至127;Char的Cache:0至127。

引用
理解Java Integer的緩衝策略

二. ThreadLocal

我這裡不再贅述ThreadLocal是什麼、解決什麼問題、實現原理、應用情境等,網上博文非常豐富,可移步至深入剖析ThreadLocal。
這裡主要是分析下ThreadLocal在父子線程中共用的問題。
ThreadLocal不提供對子線程共用父線程的ThreadLocal中儲存的value的支援,ThreadLocal的get方法返回與當前線程有關的ThreadLocalMap中的key/value,如:

/* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ThreadLocal.ThreadLocalMap threadLocals = null;

每個線程在建立的時候,都會初始化ThreadLocalMap的Null 參考。 子線程在建立時ThreadLocaMap是null,所以不共用父線程的ThreadLocalMap中key/value。

但是有很多時候,實際需求需要共用父線程的一些狀態值。 這種情況,java也對此提供了支援,只能說設計者們的腦洞大開。
java中引入另一個InheritableThreadLocal類對此提供支援,類名給出了用途的最好表示:可繼承的ThreadLocal

/* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ThreadLocal.ThreadLocalMap threadLocals = null;

同理,每個線程在建立的時候都會初始化InheritableThreadLocal
的引用,然後線上程執行初始化的生命週期階段時,對該變數進行初始化操作,如:

    if (parent.inheritableThreadLocals != null)        this.inheritableThreadLocals =            ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

線程的初始化周期中,首先判斷父線程的ThreadLocal是否為空白,如果不為空白則根據父線程的inheritableThreadLocals建立子線程的inheritableThreadLocals。
InheritableThreadLocal的實現也非常簡單:

  • childValue: 計運算元線程的初始化值,從這個方法中可以知道,子線程使用的是父線程中的value,並不是拷貝,如果需要使用副本拷貝,可以繼承重寫
  • getMap: 返回當前線程持有的inheritableThreadLocals
  • createMap: 如果當前線程的inheritableThreadLocals是空,則建立一個

以上三個api都是重寫ThreadLocal的。

Java中Integer和ThreadLocal

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.