WeakHashMap和Java引用類型詳細解析

WeakHashMap是種弱引用的HashMap,這是說,WeakHashMap里的key值如果沒有外部強引用,在垃圾回收之后,WeakHashMap的對應內容也會被移除掉。

1.1?Java的引用類型

在講解WeakHashMap之前,我們需要了解Java中引用的相關類:

ReferenceQueue,引用隊列,與某個引用類綁定,當引用死亡后,會進入這個隊列。

HardReference,強引用,任何以類似String str=new String()建立起來的引用,都是強引用。在str指向另一個對象或者null之前,該String對象都不會被GC(Garbage Collector垃圾回收器)回收;

WeakReference,弱引用,可以通過java.lang.ref.WeakReference來建立,當GC要求回收對象時,它不會阻止對象被回收,該對象會立刻被回收;

SoftReference,軟引用,可以通過java.lang.ref.SoftReference來建立,和弱引用一樣,當GC要求回收時,它不會阻止對象被回收,但不同的是該對回收過程會被延遲,必須要等到JVM heap內存不夠用,接近產生OutOfMemory錯誤時,才會回收;

PhantomReference,虛引用,可以通過java.lang.ref.PhantomPeference來建立,這種類型的引用很特別,大多數時間,無法通過它拿到其引用的對象,但是,當這個對象死亡的時候,該引用還是會進入ReferenceQueue隊列。

下面提供一個例子來分別說明它們的作用:

ReferenceQueue<Ref> queue?= new?ReferenceQueue<Ref>();

// 創建一個弱引用

WeakReference<Ref> weak?= new?WeakReference<Ref>(new?Ref("Weak"),queue);

// 創建一個虛引用

PhantomReference<Ref> phantom?= new?PhantomReference<Ref>(new?Ref(

"Phantom"), queue);

// 創建一個軟引用

SoftReference<Ref> soft?= new?SoftReference<Ref>(new?Ref("Soft"),queue);

?

System.out.println("引用內容:");

System.out.println(weak.get());

System.out.println(phantom.get());

System.out.println(soft.get());

?

System.out.println("被回收的引用:");

for?(Reference?r?= null; (r?= queue.poll()) != null;) {

System.out.println(r);

}

?

Ref這個類是個自定義的測試類,源碼如下所示:

class?Ref {

Object v;

Ref(Object v) {

this.v?= v;

}

public?String toString() {

return?this.v.toString();

}

}

?

在這個例子里,分別創建了弱引用、虛引用和軟引用,get()方法用于獲取它們引用的Ref對象,可以注意到,Ref對象在外部并沒有任何引用,所以,在某個時間點,GC應當會回收對象。來看看代碼執行的結果:

引用內容:

Weak

null

Soft

被回收的引用:

可以看到,弱引用和軟引用的對象還是可達的,但是虛引用是不可達的。被回收的引用沒有內容,說明GC還沒有回收它們。

這證實了虛引用的性質

虛引用非常弱,以至于它自己也找不到自己的引用內容。

對之前的代碼進行改造,在輸出內容前加入代碼:

// 強制垃圾回收

System.gc();

再執行一次,得到結果:

引用內容:

null

null

Soft

被回收的引用:

java.lang.ref.WeakReference@3b764bce

java.lang.ref.PhantomReference@759ebb3d

現在可達的引用只剩下Soft了,引用隊列里多出了兩條引用,說明WeakReference和PhantomReference的對象被回收。

再修改一次代碼,讓WeakPeference和PhantomReference去引用一個強引用對象:

Ref wr?= new?Ref("Hard");

WeakReference<Ref> weak?= new?WeakReference<Ref>(wr, queue);

PhantomReference<Ref> phantom?= new?PhantomReference<Ref>(wr, queue);

輸出結果如下所示:

引用內容:

Hard

null

Soft

被回收的引用:

這證實了弱引用的性質

弱引用的對象,如果沒有被強引用,在垃圾回收后,引用對象會不可達。

?

1.2?WeakHashMap實現方式

WeakHashMap利用了ReferenceQueue和WeakReference來實現它的核心功能:當key值沒有強引用的時候,從WeakHashMap里移除。

先來看看WeakHashMap的鍵值對實體類WeakHashMap.Entry的實現:

?private?static?class?Entry<K,V> extends?WeakReference<Object> implements?Map.Entry<K,V> {

????????Entry(Object key, V value,

??????????????ReferenceQueue<Object> queue,

??????????????int?hash, Entry<K,V> next) {

????????????super(key, queue);

????????????this.value?= value;

????????????this.hash??= hash;

????????????this.next??= next;

????????}

????...

}

關鍵注意兩處:

1、Entry繼承自WeakReference;

2、Entry本身沒有保存key值,而是把key作為WeakReference的引用對象交給了super構造。

這說明,Entry是個針對key值的弱引用。

WeakHashMap實現清除陳舊實體的方法是expungStaleEntries(),其源碼實現如下:

private?void?expungeStaleEntries() {

????//遍歷引用隊列,找到每一個被GC收集的對象

????????for?(Object x; (x?= queue.poll()) != null; ) {

????????????synchronized?(queue) {

????????????????@SuppressWarnings("unchecked")

????????????????????Entry<K,V> e?= (Entry<K,V>) x;

????????????????int?i?= indexFor(e.hash, table.length);

????????????????//從鏈表里移除該實體

????????????????Entry<K,V> prev?= table[i];

????????????????Entry<K,V> p?= prev;

????????????????while?(p?!= null) {

????????????????????Entry<K,V> next?= p.next;

????????????????????if?(p?== e) {

????????????????????????if?(prev?== e)

????????????????????????????table[i] = next;

????????????????????????else

????????????????????????????prev.next?= next;

????????????????????????//幫助GC執行

????????????????????????e.value?= null;

????????????????????????size--;

????????????????????????break;

????????????????????}

????????????????????prev?= p;

????????????????????p?= next;

????????????????}

????????????}

????????}

????}

?

expungStaleEntries()方法會在resize、put、get、forEach方法里被調用。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/282968.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/282968.shtml
英文地址,請注明出處:http://en.pswp.cn/news/282968.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

KVOController代碼分析和踩坑

KVOController是FaceBook的一個開源庫&#xff0c;提供了方便的姿勢讓你去使用KVO。 github.com/facebook/KV… 大概的用法如下&#xff1a; [self.KVOController observe:target keyPath:keyPath options:NSKeyValueObservingOptionNew block:^(id observer, id object, NSDic…

java中compareto方法詳解,Java中compareTo()方法的詳解

例如&#xff1a;String a "abc";String b "abc";System.out.println("num "a.compareTo(b));a是String類型的字符串,它的比較用compareTo方法,它從第一位開始比較, 如果遇到不同的字符,則馬上返回這兩個字符的ascii值差值.返回值是int類型1.…

《ASP.NET Core 6框架揭秘》實例演示[21]:如何承載你的后臺服務

借助 .NET提供的服務承載&#xff08;Hosting&#xff09;系統&#xff0c;我們可以將一個或者多個長時間運行的后臺服務寄宿或者承載我們創建的應用中。任何需要在后臺長時間運行的操作都可以定義成標準化的服務并利用該系統來承載&#xff0c;ASP.NET Core應用最終也體現為這…

使用DBCA工具創建自己的數據庫

ylbtech-Oracle&#xff1a;使用DBCA工具創建自己的數據庫 DBCA創建數據庫 默認安裝的Oracle數據庫一般不能滿足實際應用的需求&#xff0c;例如數據庫名稱、數據庫塊的大小等都需要修改&#xff0c;那么我們應該自己創建一個滿足實際應用系統需要的Oracle數據實例&#xff08;…

免去架構算法調優,如何讓你的系統風馳電掣?|圖說

通用計算場景下的云服務器領域從來都是兵家必爭之地&#xff0c;價格戰曾打了一波又一波&#xff0c;可用戶痛點卻依然是“頑疾”。由于采用的基礎硬件、架構和調優技術千差萬別&#xff0c;類似配置的云服務器之間存有較大的性能差異。 但市面上五花八門的云服務器不絕于耳&am…

PHP URL的處理函數,php中url處理函數總結

在php中url處理函數有很多,如有:http_build_query,compact,urldecode、urlencode,parse_url,rawurldecode等等函數。http_build_query(PHP 5) http_build_query — 生成 URL-encode 之后的請求字符串,實例代碼如下:$dataarray(foo>bar,baz>boom,cow>milk,php>hyper…

記一次 .NET 某數控機床控制程序 卡死分析

一&#xff1a;背景 1. 講故事前段時間有位朋友微信上找到我&#xff0c;說它的程序出現了卡死&#xff0c;讓我幫忙看下是怎么回事&#xff1f; 說來也奇怪&#xff0c;那段時間求助卡死類的dump特別多&#xff0c;被迫訓練了一下對這類問題的洞察力 &#x1f604;&#x1f60…

TODO-MVP-Loaders源碼體驗

大家好&#xff0c;我是蒼王。以下是我這個系列的相關文章&#xff0c;有興趣可以參考一下&#xff0c;可以給個喜歡或者關注我的文章。[Android]如何做一個崩潰率少于千分之三噶應用app--章節列表相信有關注我的人&#xff0c;都會看過我上一編介紹的Todo-mvp源碼體驗&#xf…

.NET Framework 4.8預覽

雖然人們的大多數關注點都在.NET Core上&#xff0c;但經典的.NET Framework仍然在開發中。.NET 4.8的“早期訪問”預覽版表明了微軟最關心的領域包括高DIP、可訪問性和并發性。\\.NET 4.8預計將于2019年發布。目前的預期是&#xff0c;它將在稍后的Windows 10 build 1607上運行…

java項目商品的排名,分析了5萬個開源項目,得出的排名前16的Java工具類

原文:https://www.jianshu.com/p/9e937d178203在Java中&#xff0c;工具類定義了一組公共方法&#xff0c;這篇文章將介紹Java中使用最頻繁及最通用的Java工具類。以下工具類、方法按使用流行度排名&#xff0c;參考數據來源于Github上隨機選取的5萬個開源項目源碼。一. org.ap…

IDEA遠程調試

參考鏈接&#xff1a;http://www.cnblogs.com/wy2325/p/5600232.html 調試端口是catlina.sh中的 JAVA_OPTS-agentlib:jdwptransportdt_socket,servery,suspendn,address5023 -Xms1024m -Xmx3072m -XX:MaxNewSize128m #!/bin/sh 配置的端口&#xff0c;是address ******&#…

ASP.NETCoreWeb開發之OptionsPattern

這節我們來講一下&#xff0c;在ASP.NET Core Web開發中&#xff0c;讀取配置文件信息的新方式&#xff1a;Options。前言 /Options在ASP.NET Web框架中&#xff0c;我們讀取配置文件中的數據&#xff0c;在不使用第三方框架的情況下&#xff0c;可能需要通過ConfigurationMana…

SpringMVC執行流程圖

2019獨角獸企業重金招聘Python工程師標準>>> 轉載于:https://my.oschina.net/u/2607324/blog/827946

CC框架實踐(1):實現登錄成功再進入目標界面功能

在掘金上看到這篇文章&#xff1a;android 關于先登錄成功后再進入目標界面的思考,作者對實現登錄成功后再跳轉到目標界面功能作了比較詳細的分析&#xff0c;對比了一些已有的實現方案并指出存在的問題。最終&#xff0c;作者實現了一個可同時添加多個條件判斷攔截的方案&…

yum search php7,yum install php7 in centos6

如果有安裝的PHP包&#xff0c;先刪除他們yum list installed | grep phpyum remove php.x86_64 php-cli.x86_64 php-common.x86_64 php-gd.x86_64 php-ldap.x86_64 php-mbstring.x86_64 php-mcrypt.x86_64 php-mysql.x86_64 php-pdo.x86_64yum 安裝我們需要的軟件1.安裝epel軟…

CentOS 7系統安裝配置圖解教程

操作系統&#xff1a;CentOS 7.3 備注&#xff1a; CentOS 7.x系列只有64位系統&#xff0c;沒有32位。生產服務器建議安裝CentOS-7-x86_64-Minimal-1611.iso版本 一、安裝CentOS 7.3 成功引導系統后&#xff0c;會出現下面的界面 界面說明&#xff1a; Install CentOS 7 #安裝…

這份《.NET/C#面試手冊》超神啦!

這幾天給.neter們整理了一份《.NET/C#面試手冊》&#xff0c;目前大約4萬字左右&#xff0c;初衷也很簡單&#xff0c;就是希望在面試的時候能夠幫助到大家&#xff0c;減輕大家的負擔和節省時間。對于沒有跳槽打算的也可以復習一下相關知識點&#xff0c;就當是查缺補漏&#…

Dinic算法----最大流常用算法之一

——沒有什么是一個BFS或一個DFS解決不了的&#xff1b;如果有&#xff0c;那就兩個一起。 最大流的$EK$算法雖然簡單&#xff0c;但時間復雜度是$O(nm^2)$&#xff0c;在競賽中不太常用。 競賽中常用的$Dinic$算法和$SAP$&#xff0c;其實也不太難。 那么&#xff0c;$Dinic$算…

springcloud~Eureka實例搭建

服務端 build.gradle配置 dependencies {compile(org.springframework.cloud:spring-cloud-starter-netflix-eureka-server)testCompile(org.springframework.boot:spring-boot-starter-test) }dependencyManagement {imports {mavenBom "org.springframework.cloud:sprin…

php5.3教程,Php 5.3發布

PHP 5.3.4 特性&#xff1a; 增加對zip 流的統計支持 新增 follow_location (默認啟用)支持 增加一個 3rd parameter to get_html_translation_table Implemented FR #52348, added new constant ZEND_MULTIBYTE to detect zend multibyte at runtime. Multiple improvements t…