淺談Java的WeakHashMap源碼
WeakHashMap源碼解析
JDK版本
JDK 1.8.0_110
總體介紹
介紹一個特殊的成員: WeakHashMap,從名字可以看出它是某種 Map。
它的特殊之處在于 WeakHashMap 里的 entry 可能會被GC自動刪除,即使程序員沒有調(diào)用 remove() 或者 clear() 方法。
更直觀的說,當(dāng)使用 WeakHashMap 時,即使沒有顯示的添加或刪除任何元素,也可能發(fā)生如下情況:
- 調(diào)用兩次size()方法返回不同的值;
- 兩次調(diào)用isEmpty()方法,第一次返回false,第二次返回true;
- 兩次調(diào)用containsKey()方法,第一次返回true,第二次返回false,盡管兩次使用的是同一個key;
- 兩次調(diào)用get()方法,第一次返回一個value,第二次返回null,盡管兩次使用的是同一個對象。
遇到這么奇葩的現(xiàn)象,是不是覺得使用者一定會瘋掉?
其實(shí)不然,WeakHashMap的這個特點(diǎn)特別適用于需要緩存的場景。
在緩存場景下,由于內(nèi)存是有限的,不能緩存所有對象;對象緩存命中可以提高系統(tǒng)效率,但緩存MISS也不會造成錯誤,因?yàn)榭梢酝ㄟ^計算重新得到。
要明白 WeakHashMap 的工作原理,還需要引入一個概念 : 弱引用(WeakReference)。
我們都知道Java中內(nèi)存是通過GC自動管理的,GC會在程序運(yùn)行過程中自動判斷哪些對象是可以被回收的,并在合適的時機(jī)進(jìn)行內(nèi)存釋放。
GC判斷某個對象是否可被回收的依據(jù)是,是否有有效的引用指向該對象。如果沒有有效引用指向該對象(基本意味著不存在訪問該對象的方式),那么該對象就是可回收的。這里的有效引用 并不包括弱引用。
也就是說,雖然弱引用可以用來訪問對象,但進(jìn)行垃圾回收時弱引用并不會被考慮在內(nèi),僅有弱引用指向的對象仍然會被GC回收。
WeakHashMap 內(nèi)部是通過弱引用來管理 entry 的,弱引用的特性對應(yīng)到 WeakHashMap 上意味著什么呢?
將一對 key, value 放入到WeakHashMap里并不能避免該 key 值被GC回收,除非在 WeakHashMap之外還有對該 key 的強(qiáng)引用。
Java中引用也是分種類的,并且不同種類的引用對GC的影響不同就夠了。
具體實(shí)現(xiàn)
WeakHashMap的存儲結(jié)構(gòu)類似于Map
Weak HashSet
Java Collections工具類給出了解決方案, Collections.newSetFromMap(Map<E,Boolean> map) 方法可以將任何 Map包裝成一個Set。
通過如下方式可以快速得到一個 Weak HashSet:
// 將WeakHashMap包裝成一個Set Set<Object> weakHashSet = Collections.newSetFromMap( new WeakHashMap<Object, Boolean>());
不出所料, newSetFromMap() 方法只是對傳入的 Map做了簡單包裝:
// Collections.newSetFromMap()用于將任何Map包裝成一個Set public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) { return new SetFromMap<>(map); } private static class SetFromMap<E> extends AbstractSet<E> implements Set<E>, Serializable { private final Map<E, Boolean> m; // The backing map private transient Set<E> s; // Its keySet SetFromMap(Map<E, Boolean> map) { if (!map.isEmpty()) throw new IllegalArgumentException("Map is non-empty"); m = map; s = map.keySet(); } public void clear() { m.clear(); } public int size() { return m.size(); } public boolean isEmpty() { return m.isEmpty(); } public boolean contains(Object o) { return m.containsKey(o); } public boolean remove(Object o) { return m.remove(o) != null; } public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; } public Iterator<E> iterator() { return s.iterator(); } public Object[] toArray() { return s.toArray(); } public <T> T[] toArray(T[] a) { return s.toArray(a); } public String toString() { return s.toString(); } public int hashCode() { return s.hashCode(); } public boolean equals(Object o) { return o == this || s.equals(o); } public boolean containsAll(Collection<?> c) {return s.containsAll(c);} public boolean removeAll(Collection<?> c) {return s.removeAll(c);} public boolean retainAll(Collection<?> c) {return s.retainAll(c);} // addAll is the only inherited implementation ...... }
到此這篇關(guān)于淺談Java的WeakHashMap源碼的文章就介紹到這了,更多相關(guān)WeakHashMap源碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot配置Hikari數(shù)據(jù)庫連接池的詳細(xì)步驟
Spring Boot是一個開源的Java框架,它簡化了基于Spring的應(yīng)用程序的開發(fā)和部署,HikariCP是一個高性能的Java數(shù)據(jù)庫連接池,被廣泛應(yīng)用于Java開發(fā)領(lǐng)域,它是目前最快和最輕量級的連接池之一,本文介紹了SpringBoot配置Hikari數(shù)據(jù)庫連接池的詳細(xì)步驟,需要的朋友可以參考下2024-08-08jpa多數(shù)據(jù)源時Hibernate配置自動生成表不生效的解決
這篇文章主要介紹了jpa多數(shù)據(jù)源時Hibernate配置自動生成表不生效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02SpringBoot整合Redis實(shí)現(xiàn)刷票過濾功能
隨著互聯(lián)網(wǎng)的不斷發(fā)展,網(wǎng)站或APP的用戶流量增加,也衍生出了一些惡意刷量等問題,給數(shù)據(jù)分析及運(yùn)營帶來極大的困難,所以本文使用SpringBoot和Redis實(shí)現(xiàn)一個刷票過濾功能,需要的可以參考一下2023-06-06Spring Boot緩存實(shí)戰(zhàn) Caffeine示例
本篇文章主要介紹了Spring Boot緩存實(shí)戰(zhàn) Caffeine示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02SpringBoot實(shí)現(xiàn)本地上傳文件到resources目錄
Java后端項(xiàng)目上傳文件是一個很常見的需求,這篇文章主要為大家介紹了SpringBoot如何實(shí)現(xiàn)本地上傳文件到resources目錄永久保存下載,需要的可以參考一下2023-07-07一文帶你了解微服務(wù)架構(gòu)中的"發(fā)件箱模式"
微服務(wù)架構(gòu)如今非常的流行,這個架構(gòu)下可能經(jīng)常會遇到“雙寫”的場景。本文就和大家分享一個“發(fā)件箱模式”,?感興趣的小伙伴可以了解一下2023-01-01Spring Cloud Gateway調(diào)用Feign異步問題記錄
這篇文章主要介紹了Spring Cloud Gateway調(diào)用Feign異步問題記錄,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04