java 引用隊列_Java中管理資源的引用隊列相關原理解析

當對象改變其可達性狀態時,對該對象的引用就可能會被置于引用隊列(reference queue)中。這些隊列被垃圾回收器用來與我們的代碼溝通有關對象可達性變化的情況。這些隊列是探測可達性變化的最佳方式,盡管我們也可以通過檢查get方法的返回值是不是null來探測對象的可達性變化。

引用對象在構造時可以與特定隊列建立關聯。Reference的每一個子類都提供了如下形式的構造器:

.public Strength Reference (T referent, ReferenceQueueq):該方法用給定的指稱對象創建新的引用對象,并且把該引用對象注冊到給定的隊列中。弱引用和軟引用在垃圾回收器確定它們的指稱對象進人它們所表示的特定可達性狀態之后,就會被插人到隊列中,并且這兩種引用在插人隊列前都會被清除。虛引用也會在垃圾回收器確定它的指稱對象進入虛可達狀態之后,被插入到隊列中,但是它們不會被清除。一旦引用對象被垃圾回收器插人到隊列中,其get方法的返回值就肯定會是null,因此該對象就再也不能復活了。

將引用對象注冊到引用隊列中并不會創建隊列和引用對象之間的引用。如果我們的引用對象本身變成了不可達的,那么它就不能插人隊列了。因此我們的應用需要保持對所有引用對象的強引用。

ReferenceQueue類提供了三個用來移除隊列中引用的方法:

.public Reference < ? extends下>poll ():用于移除并返回該隊列中的下一個引用對象,如果隊列為空,則返回null.

.public Referenceremove ()throws InterruptedException:用于移除并返回該隊列中的下一個引用對象,該方法會在隊列返回可用引用對象之前一直阻塞。

.public Referenceremove (long timeout) throws interrupte-dException:用于移除并返回隊列中的下一個引用對象。該方法會在隊列返回可用引用對象之前一直阻塞,或者在超出指定超時后結束。如果超出指定超時,則返回null.如果指定超時為0,意味著將無限期地等待。

poll方法使得線程可以查詢某個引用是否在隊列中,并且在該引用存在于隊列中時執行特定的動作。remove方法可以處理更復雜(更少見)的情況,在該方法中有一個專門的線程負責從隊列中移除引用,并執行恰當的動作。這些方法的阻塞行為和object.wait中定義的阻塞行為相同。對于特定的引用,我們可以通過其isEnqueued方法來查詢它是否在隊列中,也可以通過調用其enqueue方法將其強制插入到隊列中,但是通常這種插人是由垃圾回收器完成的。

引用隊列中的虛引用可以用來確定對象何時可以被回收。我們不可能通過虛引用來訪問任何對象,即使該對象通過其他方式是可達的也是如此,因為虛引用的get方法總是返回null,事實上,用虛引用來查找要回收的對象是最安全的方法,因為弱引用和軟引用在對象可終結之后會被插人到隊列中,而虛引用是在指稱對象被終結之后插人到隊列中的,即在該對象可以執行某些操作的最后時刻之后插人隊列的,所以它是絕對安全的。如果可以的話,應該總是使用虛引用,因為其他引用會存在finalize方法使用可終結對象的可能性。

考慮一個資源管理器的例子,它可以控制外部資源集合的訪問。對象可以請求訪問某項外部資源,并且直至操作完成才結束訪問,在此之后,它們應該將所用資源返回給資源管理器。如果這項資源是共享的,它的使用權就會在多個對象之間傳遞,甚至可能會在多個線程之間傳遞,因此我們很難確定哪個對象是這項資源最后的使用者,從而也就很難確定哪段代碼將負責返回這項資源。為了處理這種情況,資源管理器可以通過將資源關聯到被稱為鍵( key)的特殊對象上,實現這項資源的自動回收。只要鍵對象是可達的,我們就認為這項資源還在使用中;只要鍵對象可以被當作垃圾回收,這項資源就會被自動釋放。下面的代碼是對上述資源的抽象表示:

interface Resource{

void use(Object key, Object…args);

void release();

}

當獲得某項資源時,其鍵對象必須提供給資源管理器。對于交還的Resource實例,只有在它得到了其對應的鍵時,才可以使用這項資源。這樣就可以確保在鍵被回收之后,它所對應的資源就不能再被使用了,即便表示這項資源的Resource對象本身可能仍然是可達的。請注意,Resource對象并未存儲對鍵對象的強引用,這一點很重要,因為這可以防止鍵對象變為不可達的,從而造成資源不能收回。Resource的實現可以嵌套在資源管理器中:

private static class ResourceImpl implements Resource{

int keyHash;

boolean needsRelease=false

ResourceImpl(Object key){

keyHash=System.identityHashCode(key);

//=set up the external resource

needsRelease=true; }

public void use(Object key,Object... args){

if (System.identityHashCode(key)!=keyHash)

throw new IlleqalArgumentException("wrong key"

//...use the resource

}

public synchronized void release(){

if (needsRelease){

needsRelease=false:

//=release the resource

}

}

}

在資源被創建時就存儲了鍵對象的散列碼,并且無論何時調用use方法,它都會檢查是否提供了相同的鍵。對資源的實際使用可能還需要進行同步,但是為了簡單起見,我們在這里把它們省略了。release方法負責釋放資源,它可以由資源的使用者在使用結束之后直接調用,也可 以由資源管理器在鍵對象不再被引用時調用。因為我們將使用獨立的線程來監視引用隊列,所以release方法必須是synchronized的,并且必須允許多次調用。

實際的資源管理器具有如下形式:

public final class ResourceManager{

final ReferenceQueue

鍵對象可以是任意對象,與讓資源管理器分配鍵對象相比,這賦予了資源使用者極大的靈活性。在調用getResource方法時,會創建一個新的Resource工mpl對象,同時會把提供給該方法的鍵傳遞給這個新的ResourceImpl對象。然后會創建一個虛引用,其指稱對象就是傳遞給該方法的鍵,之后這個虛引用會被插人到資源管理器的引用隊列中。最后所創建的虛引用和引用對象會被存儲到映射表中,這個映射表有兩個用途:一是保持所有的虛引用對象都是可達的,二是可以提供便捷的方法來查詢每個虛引用所關聯的實際的Resource對象。(另一種方式是子類化PhantomReference并將Resource對象存在一個字段中。)

如果鍵對象變成了不可達的,那么資源管理器會使用獨立的“收割機”(reaper)線程來處理資源。shutdown方法通過終止收割機線程(以響應中斷)從而導致getResource方法拋出Ille-llleStateException異常來“關閉”資源管理器。在這個簡單的設計中,任何在資源管理器關閉之后插人隊列的引用都不會得到處理。實際的收割機線程如下:

class ReaperThread extends Thread{

public void run(){

//run until interrupted

while (true){

try{

Reference ref=queue.remove();

Resource res=null;

synchronized(ResourceManager.this){

res=refs.get(ref);

refs . remove(ref);

}

res .release();

ref.clear();

}

catch (InterruptedException ex){

break;//all done

}

}

}

}

ReaperThread是內部類,并且給定的收割機線程會一直運行,直至與其相關聯的資源管理器關閉。該線程會在remove方法上阻塞,直至與特定鍵相關聯的虛引用被插人到引用隊列中為止。這個虛引用可以從映射表中獲取對Resource對象的引用,然后這一項“鍵一引用”對將會從映射表中移除。緊接著,在Resource對象上調用其release方法來釋放這項資源。最后,

虛引用被清除,使得鍵可以被回收。

作為一種替代使用獨立線程的方案,凡是在引用隊列上調用poll方法并釋放其鍵已經變為不可達的所有資源的操作都可以用getResourc“方法來替代,shutdow”方法也可以用來執行最后的poll操作。而資源管理器的語義將依賴于實際的資源類型和資源使用的模式。

使用引用隊列的設計與直接使用終結(特別是使用虛引用)的設計相比,要可靠得多。但是我們要記住,對于引用對象插入到引用隊列中的確切時間和位置都是不能確定的,我們也不能確定在應用程序終止的時候,所有可插人的引用是否都匕經插人到了引用隊列中。如果我們需要確保所有資源在應用程序終止之前都能夠被釋放掉,就必須要安裝必要的關閉掛鉤或者使用由應用程序定義的其他協議來確保實現這一點。

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

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

相關文章

Tomcat 替換項目圖標

1.首先制作一個32*32像素的圖標&#xff0c;命名為favicon.ico這里名稱必須是和Tomcat的webapps下的ROOT下的一樣。 2.把制作好的圖標放到你要部署的Web項目的images目錄下&#xff0c;如果你的Web項目有過濾器等&#xff0c;要給后綴名為.ico的圖標放行。 3.最后你就可以在你需…

hp 導出日志 遠程管理卡_惠普服務器遠程管理卡安裝詳解

可以遠程管理服務器。帶惠普基于Web的網絡資源管理和性能監視工具HP Toptools惠普遠程管理卡的主要功能是可以實現對服務器的遠程監控&#xff0c;其中包括察看日志、遠程診斷、遠程開/關機、重啟等等。基于惠普遠程管理卡的重要功能&#xff0c;本文將著重介紹惠普遠程管理卡的…

java 錯誤登陸次數_純java代碼實現登陸次數驗證,登陸錯誤5次之后鎖定30分鐘

本方法因為是根據思路純手寫&#xff0c;代碼可以再簡化&#xff0c;功能嘗試沒問題&#xff0c;最主要就是在登陸驗證中的邏輯&#xff0c;checkLogin()方法是登錄前的驗證&#xff0c;而真正的登陸方式采用的是Shiro&#xff0c;若不是采用Shiro登陸&#xff0c;將該邏輯采用…

java 監聽器 分類_java過濾器和監聽器詳解 分類: 學習專區

過濾器1、Filter工作原理(執行流程)當客戶端發出Web資源的請求時&#xff0c;Web服務器根據應用程序配置文件設置的過濾規則進行檢查&#xff0c;若客戶請求滿足過濾規則&#xff0c;則對客戶請求&#xff0f;響應進行攔截&#xff0c;對請求頭和請求數據進行檢查或改動&#x…

linux java啟動腳本文件_不錯的linux下通用的java程序啟動腳本

#!/bin/sh#該腳本為Linux下啟動java程序的通用腳本。即可以作為開機自啟動service腳本被調用&#xff0c;#也可以作為啟動java程序的獨立腳本來使用。##Author: tudaxia.com, Date: 2011/6/7##警告!!!&#xff1a;該腳本stop部分使用系統kill命令來強制終止指定的java程序進程。…

linux心跳包檢測代碼_OpenSSL心跳包越界讀敏感信息泄漏漏洞

發布日期&#xff1a;2014-04-10CVE ID&#xff1a;CVE-2014-0160受影響的軟件及系統&#xff1a;OpenSSL 1.0.1&#xff0d;OpenSSL 1.0.1fOpenSSL 1.0.2-betaOpenSSL 1.0.2-beta1未受影響的軟件及系統&#xff1a;OpenSSL 0.9.8OpenSSL 1.0.0OpenSSL 1.0.1gOpenSSL 1.0.2-bet…

mysql數據庫主要負責存儲_mysql數據庫自帶數據庫介紹

show databases&#xff1b;查看mysql自帶數據庫有information_schema&#xff0c;mysql&#xff0c; performance_schema&#xff0c; testinformation_schema數據庫有40張表&#xff0c;如下。在MySQL中&#xff0c;把 information_schema 看作是一個數據庫&#xff0c;確切說…

python 編輯數學公式_Jupyter快速編輯高大上數學公式 泰勒展開式

歡迎點擊「算法與編程之美」↑關注我們&#xff01;本文首發于微信公眾號&#xff1a;"算法與編程之美"&#xff0c;歡迎關注&#xff0c;及時了解更多此系列博客。人工智能的基礎是機器學習&#xff0c;而通過之前的幾篇博客了解到&#xff0c;機器學習的基礎是數學…

用java寫一個日歷_使用JAVA寫一個簡單的日歷

JAVA寫一個簡單的日歷import java.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date;import java.util.GregorianCalendar;import java.util.Scanner;/*** 制作一個簡單的日歷** author 這…

MySQL定時任務event,儲存過程(定時刪除指定時間前90天指定表的數據)

<span style"font-family: Microsoft YaHei; font-size: 14px;">MySQL定時任務event</span> 由于一些業務需求&#xff0c;我們可能需要定時清除數據庫一些廢棄的數據&#xff0c;可以使用mysql的存儲過程和事件來完成。 下面例子定時清除日志表tbl_base…

python慢為什么用的人還很多_為什么是所有人比python標準慢得多嗎?

通過使用生成器理解而不是列表理解&#xff0c;可以使這兩個函數更快、更具可比性。在s """import numpy as np;x, y np.random.rand(1000),np.random.rand(1000);(all((x[i], y[i])) for i in range(1000)) """timeit.timeit(s,number1000)0.…

Java規定構造方法和類名相同_不是說:java構造方法和類名一定要相同嗎?為什么我看見很多構造方法跟類名不完全一致啊?隱藏了什么嗎?...

比如以下代碼。類名不是TestCar_EX才對嗎&#xff1f;為什么構造方法名卻是Car&#xff1f;我看見很多教程都是這么寫的。暈。。。。。。。。。。。到底怎么樣才是對的啊&#xff1f;public class TestCar_EX {public static void main(String[] args) {Car c1 new Car("…

java pdf stamper_PDFStamper在幾個PDF文件上失敗(itext 5.5.1)

我嘗試使用數據填充PDF表單并獲得PDFStamper(itext版本5.5.1)以處理多個PDF文件&#xff0c;但在某些情況下它總是失敗。示例代碼&#xff1a;PdfReader reader new PdfReader(new FileInputStream("C:/Temp/source.pdf"));PdfStamper stamper new PdfStamper(read…

用獵物皮毛換酒喝java_荒野大鏢客2三星毛皮狩獵技巧分享 各種類獵物三星皮毛獲取方法...

荒野大鏢客2三星毛皮怎么獲得&#xff1f;想必很多朋友都還不是很清楚吧&#xff0c;所以呢小編今天給大家帶來的就是荒野大鏢客2三星毛皮狩獵技巧分享&#xff0c;需要的朋友還不快進來看看&#xff1f;三星毛皮狩獵技巧分享獵物體型分水嶺建議以狐貍類為例。(1)中型獵物[比狐…

Java調用WebService接口實現發送手機短信驗證碼功能,java 手機驗證碼,WebService接口調用...

近來由于項目需要&#xff0c;需要用到手機短信驗證碼的功能&#xff0c;其中最主要的是用到了第三方提供的短信平臺接口WebService客戶端接口&#xff0c;下面我把我在項目中用到的記錄一下&#xff0c;以便給大家提供個思路&#xff0c;由于本人的文采有限&#xff0c;還請大…

java中的udp丟包_UDP丟包問題

wxbcrefut&#xff1a;謝謝樓主分享&#xff0c;最近也遇到這種問題&#xff0c;我在虛機里測試(配置為8核16G內存)&#xff0c;1s接受2W條數據丟包就特別嚴重&#xff0c;我還沒有處理只是接受而已&#xff0c;不知道問題出在哪&#xff0c;求指教我是用java寫的&#xff0c;代…

java人體識別_用華為HMS ML kit人體骨骼識別技術,Android快速實現人體姿勢動作抓拍...

items results.getAnalyseList();// 開發者根據需要處理識別結果&#xff0c;例如&#xff0c;在此方法中進行相似度計算&#xff0c;從而在檢測到特定姿勢后進行拍照等操作。// 需要注意&#xff0c;這里只對檢測結果進行處理&#xff0c;不可調用ML Kit提供的其他檢測相關接…

java中select的用法_mybaties中select用法,以及常用增刪改查

查詢語句是使用 MyBatis 時最常用的元素之一select元素配置細節如下屬性描述取值默認id在這個模式下唯一的標識符&#xff0c;可被其它語句引用parameterType傳給此語句的參數的完整類名或別名resultType語句返回值類型的整類名或別名。注意&#xff0c;如果是集合&#xff0c;…

jpa java.util.map_使用JPA存儲Map String,String

JPA 2.0通過ElementCollection注釋可以支持原語集合&#xff0c;您可以將其與java.util.Map集合支持一起使用。這樣的事情應該起作用&#xff1a;Entitypublic class Example {Id long id;// ....ElementCollectionMapKeyColumn(name"name")Column(name"value&q…

Js獲取短信驗證碼前段效果

一&#xff1a;先上效果圖&#xff1a; 二&#xff1a;源代碼文件&#xff1a;reg.html: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http:…