国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

Java中的 WeakReference 和 SoftReference

2019-11-15 00:05:27
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
java中的 WeakReference 和 SoftReference

我們知道Java語(yǔ)言中沒(méi)有指針,取而代之的是引用reference。Java中的引用又可以分為四種:強(qiáng)引用,弱引用(WeakReference),軟引用(SoftReference),虛引用(PhantomReference)。其中強(qiáng)引用,就是我們平時(shí)使用的最多的最普通的引用,虛引用一般我們是沒(méi)有機(jī)會(huì)使用到的。所以我們主要了解下 WeakReference 和 SoftReference(除了上面說(shuō)的四種引用之外,其實(shí)還有一種引用——原子引用AtomicReference,用于并發(fā)編程環(huán)境)。

1. 先上一段代碼:

public class ReferenceTest {    public static void main(String[] args){        LinkedList<byte[]> list = new LinkedList<>();        for(int i=0; i<1024; i++){            list.add(new byte[1024*1024]);        }    }}

上面的代碼會(huì)拋出:Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

堆內(nèi)存溢出。因?yàn)槲覀儾粩嗟脑诙焉戏峙湟粋€(gè) 1M 大小的 byte[]對(duì)象,并且將該引用加入到 list 中,循環(huán)1024次,需要占用 1G 的堆內(nèi)存,從而導(dǎo)致 heap space OutOfMemory.

2. 我們使用 WeekReference 對(duì)代碼進(jìn)行修改:

public class ReferenceTest {    public static void main(String[] args) {        long beginTime = System.nanoTime();        LinkedList<WeakReference<byte[]>> list = new LinkedList<>();        for (int i = 0; i < 1024; i++) {            list.add(new WeakReference<>(new byte[1024 * 1024]));        }        long endTime = System.nanoTime();        System.out.PRintln(endTime - beginTime);    }}

輸出的結(jié)果:195947704 (0.19秒)

我們發(fā)現(xiàn)堆內(nèi)存溢出的錯(cuò)誤沒(méi)有了。這是什么原因呢。因?yàn)槲覀兪褂昧?弱引用WeekReference 來(lái)引用堆上的 1M 的byte[]對(duì)象,而弱引用WeekReference引用的對(duì)象,如果僅僅只被弱引用,而沒(méi)有被強(qiáng)引用的話,在下一次GC時(shí),就會(huì)回收該對(duì)象占用的內(nèi)存,所以不會(huì)內(nèi)存溢出。

3. 我們使用 SoftReference 對(duì)代碼進(jìn)行修改:

public class ReferenceTest {    public static void main(String[] args) {        long beginTime = System.nanoTime();        LinkedList<SoftReference<byte[]>> list = new LinkedList<>();        for (int i = 0; i < 1024; i++) {            list.add(new SoftReference<>(new byte[1024 * 1024]));        }        long endTime = System.nanoTime();        System.out.println(endTime - beginTime);    }}

輸出結(jié)果:1499904286 (1.5秒)

我們發(fā)現(xiàn)堆內(nèi)存溢出的錯(cuò)誤也沒(méi)有了。因?yàn)槲覀兪褂昧?軟引用SoftReference 來(lái)引用堆上的 1M 的byte[]對(duì)象,而軟引用SoftReference引用的對(duì)象,如果僅僅只被軟引用,而沒(méi)有被強(qiáng)引用的話,在內(nèi)存空間不足時(shí),GC 就會(huì)回收該對(duì)象占用的內(nèi)存,所以不會(huì)內(nèi)存溢出。

但是我們注意到 采用WeekReference和采用SoftReference所花費(fèi)的時(shí)間,有接近10被的差距。原因應(yīng)該是,SoftReference只有在內(nèi)存空間不足時(shí),GC才會(huì)回收對(duì)象占用的空間,而這時(shí)進(jìn)行的是 full GC,full GC會(huì)導(dǎo)致 STW 程序暫停,所以花費(fèi)的時(shí)間過(guò)多。

4. 總結(jié)

強(qiáng)引用:只要堆上的對(duì)象,被至少一個(gè)強(qiáng)引用所指向,那么GC就不會(huì)回收該對(duì)象的內(nèi)存空間。

弱引用:只要堆上的對(duì)象僅僅只被弱引用所指向,不管當(dāng)前內(nèi)存空間是否足夠,下次GC都會(huì)回收對(duì)象的內(nèi)存空間。

軟引用:只要堆上的對(duì)象僅僅只被軟引用所指向,并且當(dāng)內(nèi)存空間不足時(shí),GC才會(huì)回收對(duì)象的內(nèi)存空間。

WeakReference 和 SoftReference一般使用在構(gòu)造一個(gè)緩存系統(tǒng),比如使用一個(gè)map來(lái)構(gòu)造。因?yàn)榫彺嫦到y(tǒng)是一個(gè)“全生命期”的對(duì)象,系統(tǒng)停止,緩存對(duì)象才會(huì)被銷毀,所以當(dāng)我們不斷的想緩存對(duì)象中添加對(duì)象時(shí),那么就會(huì)導(dǎo)致該緩存對(duì)象map所引用的對(duì)象越來(lái)越多,而因?yàn)槭菑?qiáng)引用,這些被放進(jìn)map緩存了的對(duì)象不能被GC鎖回收,那么就導(dǎo)致系統(tǒng)堆內(nèi)存占用會(huì)越來(lái)越大,從而最終導(dǎo)致內(nèi)存溢出。

那么此時(shí)我們就可以使用 WeakReference 或 SoftReference了,將強(qiáng)引用通過(guò)WeakReference 和 SoftReference 包裝之后,變成弱引用和軟引用,那么當(dāng)緩存中的對(duì)象,僅僅被緩存map鎖引用時(shí),那么分別在下次GC和內(nèi)存不足GC時(shí)就會(huì)回收這些對(duì)象占用的內(nèi)存。其實(shí)JDK給我們提供了一個(gè)專門的類:WeakHashMap ,弱引用的hashMap,所以構(gòu)造緩存系統(tǒng)是,我們可以考慮使用它。

其實(shí)這里引出了另外一個(gè)問(wèn)題,jdk中眾多的map,我們應(yīng)該如何進(jìn)行選擇

HashMap

ConcurrentHashMap

TreeMap

WeakHashMap

LinkedHashMap

Collections.synchronizedMap

Hashtable

等等。我們?cè)谶x擇一個(gè)map時(shí),應(yīng)該好好的考慮下,那個(gè)更加適合我們的需求。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 秀山| 阜新市| 灌阳县| 奉新县| 望城县| 沙河市| 余庆县| 曲麻莱县| 龙岩市| 稷山县| 郓城县| 庄浪县| 林州市| 多伦县| 新营市| 蒙山县| 江安县| 新宁县| 昭通市| 吴江市| 耒阳市| 双辽市| 霞浦县| 高尔夫| 丹阳市| 镇远县| 抚州市| 太仆寺旗| 平昌县| 广宁县| 桃源县| 铁岭市| 清丰县| 万安县| 新余市| 通江县| 元阳县| 长岛县| 太和县| 武汉市| 湟中县|