成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Java Integer的緩存策略

endiat / 619人閱讀

摘要:整型對象在內(nèi)部實(shí)現(xiàn)中通過使用相同的對象引用實(shí)現(xiàn)了緩存和重用。這種緩存策略僅在自動(dòng)裝箱的時(shí)候有用,使用構(gòu)造器創(chuàng)建的對象不能被緩存。行的結(jié)果為而行則為。所以行的結(jié)果為而行為。中其他類似的緩存的緩存上限可以通過虛擬機(jī)參數(shù)修改,的緩存則沒法修改。

Java5為Integer的操作引入了一個(gè)新的特性,用來節(jié)省內(nèi)存和提高性能。整型對象在內(nèi)部實(shí)現(xiàn)中通過使用相同的對象引用實(shí)現(xiàn)了緩存和重用。
上面的規(guī)則默認(rèn)適用于整數(shù)區(qū)間 -128 到 +127(這個(gè)整數(shù)區(qū)間可以通過啟動(dòng)應(yīng)用的虛擬機(jī)參數(shù)修改:-XX:AutoBoxCacheMax)。這種Integer緩存策略僅在自動(dòng)裝箱(autoboxing)的時(shí)候有用,使用構(gòu)造器創(chuàng)建的Integer對象不能被緩存。Java 編譯器把原始類型自動(dòng)轉(zhuǎn)換為封裝類的過程稱為自動(dòng)裝箱(autoboxing),這相當(dāng)于調(diào)用 valueOf 方法。

 public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
}

首先看代碼:

public class TestInteger {
  public static void main(String[] args) {
    int i = 128;
    Integer i2 = 128;
    Integer i3 = new Integer(128);
    //Integer會自動(dòng)拆箱為int,所以為true
    System.out.println(i == i2);
    System.out.println(i == i3);
    System.out.println("**************");
    Integer i5 = 127;//java在編譯的時(shí)候,被翻譯成-> Integer i5 = Integer.valueOf(127);
    Integer i6 = 127;
    System.out.println(i5 == i6);//true
    Integer i9 = 128;
    Integer i10 = 128;
    System.out.println(i9 == i10);//false
    Integer ii5 = new Integer(127);
    System.out.println(i5 == ii5); //false
    Integer i7 = new Integer(128);
    Integer i8 = new Integer(123);
    System.out.println(i7 == i8);  //false
  }
}

首先,7行和8行輸出結(jié)果都為true,因?yàn)镮nteger和int比都會自動(dòng)拆箱(jdk1.5以上)。
12行的結(jié)果為true,而15行則為false。java在編譯Integer i5 = 127的時(shí)候,被翻譯成-> Integer i5 = Integer.valueOf(127);所以關(guān)鍵就是看valueOf()函數(shù)了。只要看看valueOf()函數(shù)的源碼就會明白了。JDK源碼的 valueOf函數(shù)式這樣的:

 public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
  }

看一下源碼大家都會明白,對于-128到127之間的數(shù),會進(jìn)行緩存,Integer i5 = 127時(shí),會將127進(jìn)行緩存,下次再寫Integer i6 = 127時(shí),就會直接從緩存中取,就不會new了。所以12行的結(jié)果為true,而15行為false。
對于17行和20行,因?yàn)閷ο蟛灰粯?,所以為false。
對于以上的情況總結(jié)如下:

無論如何,Integer與new Integer不會相等。不會經(jīng)歷拆箱過程,i3的引用指向堆,而i4指向?qū)iT存放他的內(nèi)存(常量池),他們的內(nèi)存地址不一樣,所以為false

兩個(gè)都是非new出來的Integer,如果數(shù)在-128到127之間,則是true,否則為false。java在編譯Integer i2 = 128的時(shí)候,被翻譯成-> Integer i2 = Integer.valueOf(128);而valueOf()函數(shù)會對-128到127之間的數(shù)進(jìn)行緩存

兩個(gè)都是new出來的,都為false

int和Integer(無論new否)比,都為true,因?yàn)闀袸nteger自動(dòng)拆箱為int再去比

AutoBoxCacheMax參數(shù)
// IntegerCache,Integer類的內(nèi)部類,注意它的屬性都是定義為static final
private static class IntegerCache {
    //緩存的下界,-128,不可變
    static final int low = -128;
    //緩存上界,暫為null
    static final int high;
    //緩存的整型數(shù)組
    static final Integer cache[];

    static {
        // 緩存上界,可以通過JVM參數(shù)來配置
        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);
            //最大的數(shù)組值是Integer.MAX_VALUE
            h = Math.min(i, Integer.MAX_VALUE - (-low));
        }
        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() {
    }
}

-XX:AutoBoxCacheMax這個(gè)參數(shù)是設(shè)置Integer緩存上限的參數(shù),在VM初始化期間java.lang.Integer.IntegerCache.high屬性可以被設(shè)置和保存在私有的系統(tǒng)屬性sun.misc.VM class中。理論上講,當(dāng)系統(tǒng)需要頻繁使用Integer時(shí),或者說堆內(nèi)存中存在大量的Integer對象時(shí),可以考慮提高Integer緩存上限,避免JVM重復(fù)創(chuàng)造對象,提高內(nèi)存的使用率,減少GC的頻率,從而提高系統(tǒng)的性能。
理論歸理論,這個(gè)參數(shù)能否提高系統(tǒng)系統(tǒng)關(guān)鍵還是要看堆中Integer對象到底有多少、以及Integer的創(chuàng)建的方式。如果堆中的Integer對象很少,重新設(shè)置這個(gè)參數(shù)并不會提高系統(tǒng)的性能。即使堆中存在大量的Integer對象,也要看Integer對象時(shí)如何產(chǎn)生的。

大部分Integer對象通過Integer.valueOf()產(chǎn)生。說明代碼里存在大量的拆箱與裝箱操作。這時(shí)候設(shè)置這個(gè)參數(shù)會系統(tǒng)性能有所提高。

大部分Integer對象通過反射,new產(chǎn)生。這時(shí)候Integer對象的產(chǎn)生大部分不會走valueOf()方法,所以設(shè)置這個(gè)參數(shù)也是無濟(jì)于事。

JDK中其他類似的緩存

Integer的緩存上限可以通過Java虛擬機(jī)參數(shù)修改,Byte、Short、Long、Character的緩存則沒法修改。

Byte

private static class ByteCache {
    private ByteCache(){}
    static final Byte cache[] = new Byte[-(-128) + 127 + 1];
    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Byte((byte)(i - 128));
    }
}

public static Byte valueOf(byte b) {
    final int offset = 128;
    return ByteCache.cache[(int)b + offset];
}

Short

private static class ShortCache {
    private ShortCache(){}
    static final Short cache[] = new Short[-(-128) + 127 + 1];
    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Short((short)(i - 128));
    }
}

public static Short valueOf(short s) {
    final int offset = 128;
    int sAsInt = s;
    if (sAsInt >= -128 && sAsInt <= 127) { // must cache
        return ShortCache.cache[sAsInt + offset];
    }
    return new Short(s);
}

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);
    }
}

public static Long valueOf(long l) {
    final int offset = 128;
    if (l >= -128 && l <= 127) { // will cache
        return LongCache.cache[(int)l + offset];
    }
    return new Long(l);
}

Character

private static class CharacterCache {
    private CharacterCache(){}
    static final Character cache[] = new Character[127 + 1];
    static {
        for (int i = 0; i < cache.length; i++)
            cache[i] = new Character((char)i);
    }
}

public static Character valueOf(char c) {
    if (c <= 127) { // must cache
        return CharacterCache.cache[(int)c];
    }
    return new Character(c);
}

示例:

public class AllCacheDemo {
    /**
     * 演示JDK內(nèi)部緩存
     */
    public static void main(String[] args) {
        Integer a = 28;
        Integer b = 28;
        println(a == b);

        Byte c = 25;
        Byte d = 25;
        println(c==d);

        Short p=12;
        Short q=12;
        println(p==q);

        Long x=127L;
        Long y=127L;
        println(x==y);

        Character m="M";
        Character n="M";
        println(m==n);
    }

    public static void println(Object o){
        System.out.println(o);
    }
}

作者:劉曉;花名:愚谷。
點(diǎn)擊 閱讀更多 查看更多詳情

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/73148.html

相關(guān)文章

  • 動(dòng)手實(shí)現(xiàn)一個(gè) LRU cache

    摘要:不過其中的流程算是一個(gè)簡易的實(shí)現(xiàn),可以對加深一些理解。實(shí)現(xiàn)二因此如何來實(shí)現(xiàn)一個(gè)完整的緩存呢,這次不考慮過期時(shí)間的問題。緩存數(shù)量超過閾值時(shí)移除鏈表尾部數(shù)據(jù)。 showImg(https://segmentfault.com/img/remote/1460000014229173?w=1408&h=872); 前言 LRU 是 Least Recently Used 的簡寫,字面意思則是最...

    Cc_2011 評論0 收藏0
  • 從零單排學(xué)Redis【白銀】

    摘要:對于數(shù)據(jù)結(jié)構(gòu)哈希表我們在上一篇也已經(jīng)詳細(xì)說了。鍵空間示意圖的數(shù)據(jù)庫就是使用字典哈希表來作為底層實(shí)現(xiàn)的,對數(shù)據(jù)庫的增刪改查都是構(gòu)建在字典哈希表的操作之上的。 前言 只有光頭才能變強(qiáng) 今天繼續(xù)來學(xué)習(xí)Redis,上一篇從零單排學(xué)Redis【青銅】已經(jīng)將Redis常用的數(shù)據(jù)結(jié)構(gòu)過了一遍了。如果還沒看的同學(xué)可以先去看一遍再回來~ 這篇主要講的內(nèi)容有: Redis服務(wù)器的數(shù)據(jù)庫 Redis對過期...

    denson 評論0 收藏0
  • SpringCloud(第 045 篇)鏈接Mysql數(shù)據(jù)庫集成Mybatis、ehcache采用M

    摘要:添加用戶接口類簡單用戶鏈接數(shù)據(jù)庫微服務(wù)通過注解標(biāo)注該類為持久化操作對象。查找用戶數(shù)據(jù)保存用戶數(shù)據(jù)更新用戶數(shù)據(jù)刪除用戶數(shù)據(jù)這是清除緩存添加緩存配置緩存配置。對象是否永久有效,一但設(shè)置了,將不起作用。設(shè)置對象在失效前允許存活時(shí)間單位秒。 SpringCloud(第 045 篇)鏈接Mysql數(shù)據(jù)庫簡單的集成Mybatis、ehcache框架采用MapperXml訪問數(shù)據(jù)庫 - 一、大致介紹...

    chenjiang3 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<