Integer類的緩存機制


一、Integer類的緩存機制

我們查看Integer的源碼,就會發現里面有個靜態內部類。

    public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        //當前值在緩存數組區間段,則直接返回該緩存值
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        //否則創建新的Integer實例
        return new Integer(i);
    }
    
    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        //IntegerCache初始化時,緩存數值為-128-127的Integer實例(默認是從-128到127)。
        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) {
                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);
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            //填充緩存數組
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }

        private IntegerCache() {}
    }

該類的作用是將數值等於-128-127(默認)區間的Integer實例緩存到cache數組中。通過valueOf()方法很明顯發現,當再次創建值在-128-127區間的Integer實例時,會復用緩存中的實例,也就是直接指向緩存中的Integer實例。

(注意:這里的創建不包括用new創建,new創建對象不會復用緩存實例,通過情景3的運行結果就可以得知)

 

二、其它具有緩存機制的類

實際上不僅僅Integer具有緩存機制,Byte、Short、Long、Character都具有緩存機制。來看看Long類中的緩存類

    private static class LongCache {
        private LongCache(){}

        static final Long cache[] = new Long[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Long(i - 128);
        }
    }

ByteCache用於緩存Byte對象,ShortCache用於緩存Short對象,LongCache用於緩存Long對象,CharacterCache用於緩存Character對象。這些類都有緩存的范圍,其中Byte,Short,Integer,Long為 -128 到 127,Character范圍為 0 到 127。除了 Integer 可以通過參數改變范圍外,其它的都不行。

 

面試題

面試題1:

    //情景1
    Integer c = 128;
    Integer d = 128;
    System.out.println(c == d);//false

    //情景2
    Integer a = 1;
    Integer b = 1;
    System.out.println(a == b);//true。b.intValue()

    //情景3
    Integer e = new Integer(1);
    Integer f = new Integer(1);
    System.out.println(e == f);//false

 

面試題2:

    //情景4
    int a = 1;
    Integer b = Integer.valueOf(1);
    Integer c = new Integer(1);

    System.out.println(a == b);//true
    System.out.println(a == c);//true

分析:a是基本類型,b和c是引用類型,兩者進行比較時有一個拆箱的過程,也就是會默認調用b和c的intValue()方法。

//拆箱
public int intValue() {
    return value;
}

最終比較的是基本類型的值,自然是相等的。

 

面試題3:

//代碼來源於《深入理解Java虛擬機》第4章4.3.1 P121。
public class SynAddRunnable implements Runnable {

    int a, b;

    public SynAddRunnable(int a, int b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public void run() {
        synchronized (Integer.valueOf(a)) {
            synchronized (Integer.valueOf(b)) {
                System.out.println(a + b);
            }
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(new SynAddRunnable(1, 2)).start();
            new Thread(new SynAddRunnable(2, 1)).start();
        }
    }
}

上面這段程序會發生死鎖。造成死鎖的原因:[-128,127]之間的數字會被緩存,而Integer.valueOf()會返回緩存的對象。因此代碼中200次for循環實際上總共只創建了兩個對象,當線程A持有Integer.valueOf(1)時,如果線程B持有Integer.valueOf(2),則就會出現死鎖,屬於動態鎖順序死鎖

 

總結

1.具有緩存機制的類?

Byte、Short、Integer、Long、Character都具有緩存機制。緩存工作都是在靜態塊中完成,在類生命周期(loading verify prepare resolving initial using unload)的初始化階段執行。

2.緩存范圍?

Byte,Short,Integer,Long為 -128 到 127

Character范圍為 0 到 127

 

除了Integer可以指定緩存范圍,其它類都不行。Integer的緩存上界high可以通過jvm參數-XX:AutoBoxCacheMax=size指定,取指定值與127的最大值並且不超過Integer表示范圍,而下界low不能指定,只能為-128。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM