四種引用類型在JAVA Springboot中的使用詳解
概念介紹
不同的引用類型,主要體現(xiàn)的是對象不同的可達(dá)性(reachable)狀態(tài)和對垃圾收集的影響。
01.??強(qiáng)引用
這個就是我們創(chuàng)建的普通對象了~ 當(dāng)該對象被顯示地賦值為?null?時,或者沒有被其他存活的對象繼續(xù)引用時,它就會成為垃圾收集器的目標(biāo),等待被收回
02.??軟引用
軟引用(?SoftReference
?) , 當(dāng)內(nèi)存不足?時會被回收
比如
被回收后,這里會打印?null?而不是?Java4ye
03.??弱引用
弱引用(?WeakReference?) , 當(dāng)?垃圾回收器?進(jìn)行垃圾回收時,無論內(nèi)存足與否,它都會被垃圾回收器回收
比如
被回收后,這里也是會打印?null
?而不是?Java4ye
04.??虛引用
虛引用(?ReferenceQueue?
) , 這個也是隨時會被回收,不過它的作用更像一個標(biāo)記,當(dāng)對象被回收時,它不為?null?,但是要注意,無論什么時候去調(diào)用 虛引用的?get?方法,都只能獲取到一個?null?值。
為一個對象設(shè)置虛引用關(guān)聯(lián)的唯一目的就是能在這個對象被收集器回收時收到一個系統(tǒng)通知 ——?<<深入理解Java虛擬機(jī)>>
這里引用 http://www.javashuo.com/article/p-zyvdcbhl-nb.html 該文章的例子
User user = new User(1, "Java4ye"); ReferenceQueue<User> userReferenceQueue = new ReferenceQueue<>(); // 創(chuàng)建User對象的虛引用 PhantomReference<User> phantomReference = new PhantomReference<>(user, userReferenceQueue); // 去掉強(qiáng)引用 user = null; System.out.println(phantomReference.get()); // 手動觸發(fā)GC System.gc(); System.out.println("GC: " + phantomReference.get()); Reference<? extends User> reference = null; try { reference = userReferenceQueue.remove(1000); } catch (InterruptedException e) { e.printStackTrace(); } if (reference != null) { System.out.println("對象User被回收了:"); }
對象可達(dá)性
那么 簡單介紹完上面的?4?種引用后,我們再來看看它的可達(dá)性~
如圖~
- 強(qiáng)可達(dá): 比如 創(chuàng)建一個對象時,創(chuàng)建它的線程對該對象就是強(qiáng)可達(dá)
- 軟可達(dá): 只能通過軟引用訪問
- 弱可達(dá): 只能通過弱引用訪問
- 虛可達(dá): 當(dāng)對象沒有?強(qiáng),軟,弱?引用關(guān)聯(lián)時,并且?finalize?過,就會進(jìn)入該狀態(tài)
- 不可達(dá): 意味著該對象可以被清除了。
通過最開始的代碼例子和上面的圖(雙向箭頭)我們還可以發(fā)現(xiàn),軟引用和弱引用和強(qiáng)引用這三者間可以進(jìn)行轉(zhuǎn)換( 通過?Reference
?的?get()
?可獲取到原對象),這意味著:
對于軟引用、弱引用之類,垃圾收集器可能會存在二次確認(rèn)的問題,以保證處于弱引用狀態(tài)的對象,沒有改變?yōu)閺?qiáng)引用。
在?JDK8
?中,還可以通過 指定參數(shù)打印引用的相關(guān)信息
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintReferenceGC
在?JDK8
?中使用?ParrallelGC?
收集的垃圾回收日志 (大佬 pdf 中的例子)
0.403: [GC (Allocation Failure) 0.871: [SoftReference, 0 refs, 0.0000393 secs]0.871: [WeakReference, 8 refs, 0.0000138 secs]0.871: [FinalReference, 4 refs, 0.0000094 secs]0.871:
[PhantomReference, 0 refs, 0 refs, 0.0000085 secs]0.871: [JNI Weak Reference, 0.0000071 secs][PSYoungGen: 76272K->10720K(141824K)] 128286K->128422K(316928K), 0.4683919 secs] [Times:
user=1.17 sys=0.03, real=0.47 secs]
再記錄下這個點(diǎn)??
通過底層API來達(dá)到強(qiáng)引用??
Springboot源碼中的使用
嘿嘿 終于來到重點(diǎn)了 ,正如開頭提到的~?4ye?也是在?Springboot?
源碼中看到這個
ConcurrentReferenceHashMap
?才想起要寫一下這篇文章滴?
那么這個?ConcurrentReferenceHashMap?
到底有什么作用呢?
ConcurrentReferenceHashMap?能指定所存放對象的引用級別
默認(rèn)情況下是?軟引用級別
比如 在 Springboot自動裝配原理探索 一文中提到的?Springboot SPI 機(jī)制?
其中的主角:?SpringFactoriesLoader
源碼如下:
還有自動配置過程中的注解掃描?AnnotationsScanner
以及在 萬字長文,帶你快速上手這些池化技術(shù)! 一文中出現(xiàn)的?異步任務(wù)線程池:?ThreadPoolTaskExecutor
源碼如下:?(可以看到這里指明了是?弱引用級別)
總結(jié)
看完上面的例子,覺得可以模仿下?Springboot?的?ConcurrentReferenceHashMap?,對對象進(jìn)行一個合理的存儲,間接地優(yōu)化jvm?,提高垃圾回收的效率。這兩個別搞混了:?軟引用,內(nèi)存不足時回收;弱引用,在進(jìn)行垃圾回收時,不管內(nèi)存足與否,都會被回收
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Java的LinkedHashMap的實現(xiàn)原理詳解
這篇文章主要介紹了Java的LinkedHashMap的實現(xiàn)原理詳解,???LinkedHashMap是Map接口的哈希表和鏈接列表實現(xiàn),具有可預(yù)知的迭代順序,此實現(xiàn)提供所有可選的映射操作,并允許使用null值和null鍵,此類不保證映射的順序,特別是它不保證該順序恒久不變,需要的朋友可以參考下2023-09-09RabbitMQ消息隊列中多路復(fù)用Channel信道詳解
這篇文章主要介紹了RabbitMQ消息隊列中多路復(fù)用Channel信道詳解,消息Message是指在應(yīng)用間傳送的數(shù)據(jù),消息可以非常簡單,比如只包含文本字符串,也可以更復(fù)雜,可能包含嵌入對象,需要的朋友可以參考下2023-08-08Netty分布式NioSocketChannel注冊到selector方法解析
這篇文章主要為大家介紹了Netty分布式源碼分析NioSocketChannel注冊到selector方法的解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03