一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語言 - JAVA教程 - Java中管理資源的引用隊列相關(guān)原理解析

Java中管理資源的引用隊列相關(guān)原理解析

2020-03-13 13:12爪哇小博 JAVA教程

這篇文章主要介紹了Java中管理資源的引用隊列相關(guān)原理解析,涉及到Java的垃圾回收機制方面的知識,需要的朋友可以參考下

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

  引用對象在構(gòu)造時可以與特定隊列建立關(guān)聯(lián)。Reference的每一個子類都提供了如下形式的構(gòu)造器:

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

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

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

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

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

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

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

?
1
2
3
4
5
6
7
interface Resource{
 
void use(Object key, Object…args);
 
void release();
 
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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
 
}
 
}
 
}

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

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

?
1
2
3
public final class ResourceManager{
 
final ReferenceQueue

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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是內(nèi)部類,并且給定的收割機線程會一直運行,直至與其相關(guān)聯(lián)的資源管理器關(guān)閉。該線程會在remove方法上阻塞,直至與特定鍵相關(guān)聯(lián)的虛引用被插人到引用隊列中為止。這個虛引用可以從映射表中獲取對Resource對象的引用,然后這一項“鍵一引用”對將會從映射表中移除。緊接著,在Resource對象上調(diào)用其release方法來釋放這項資源。最后,

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

  作為一種替代使用獨立線程的方案,凡是在引用隊列上調(diào)用poll方法并釋放其鍵已經(jīng)變?yōu)椴豢蛇_的所有資源的操作都可以用getResourc“方法來替代,shutdow”方法也可以用來執(zhí)行最后的poll操作。而資源管理器的語義將依賴于實際的資源類型和資源使用的模式。

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

延伸 · 閱讀

精彩推薦
  • JAVA教程簡單介紹Java編程中的線程池

    簡單介紹Java編程中的線程池

    這篇文章主要介紹了Java編程中的線程池,進程和線程的并發(fā)是Java編程中的重要環(huán)節(jié),需要的朋友可以參考下 ...

    捏造的信仰4542020-01-04
  • JAVA教程Java函數(shù)式編程(七):MapReduce

    Java函數(shù)式編程(七):MapReduce

    這篇文章主要介紹了Java函數(shù)式編程(七):MapReduce,本文是系列文章的第7篇,其它文章請參閱本文底部的相關(guān)文章,需要的朋友可以參考下 ...

    有孚2142019-12-01
  • JAVA教程java中List集合及其遍歷詳解

    java中List集合及其遍歷詳解

    這篇文章主要介紹了java中List集合及其遍歷詳解的相關(guān)資料,需要的朋友可以參考下 ...

    hebedich2852019-12-25
  • JAVA教程Java獲取mac地址的方法

    Java獲取mac地址的方法

    這篇文章主要介紹了Java獲取mac地址的方法,涉及java針對系統(tǒng)硬件及IO操作的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下 ...

    fzhlee4532019-12-28
  • JAVA教程淺析java中Integer傳參方式的問題

    淺析java中Integer傳參方式的問題

    以下是對java中Integer傳參方式的問題進行了詳細的介紹,需要的朋友可以過來參考下 ...

    java之家3782019-10-12
  • JAVA教程Java的Spring框架下RMI與quartz的調(diào)用方法

    Java的Spring框架下RMI與quartz的調(diào)用方法

    這篇文章主要介紹了Java的Spring框架下RMI與quartz的調(diào)用方法,Spring是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下 ...

    小李飛刀84392020-01-21
  • JAVA教程JAVA時間日期處理類實例

    JAVA時間日期處理類實例

    這篇文章主要介紹了JAVA時間日期處理類,可實現(xiàn)遍歷兩個日期之間的每一天的功能,涉及針對日期的常見操作技巧,需要的朋友可以參考下 ...

    MagicYK2952019-12-16
  • JAVA教程Java中的Object類詳細介紹

    Java中的Object類詳細介紹

    這篇文章主要介紹了Java中的Object類詳細介紹,本文講解了Object類的作用、Object類的主要方法、Object類中不能被重寫的方法、Object類的equals方法重寫實例等內(nèi)...

    junjie2902019-12-23
主站蜘蛛池模板: 成年男女免费大片在线观看 | 午夜私人影院在线观看 | 国产福利自产拍在线观看 | 久久视频精品3线视频在线观看 | 丝袜老师好湿好紧我要进去了 | 日本阿v在线播放 | 日韩免费在线视频观看 | 性色视频免费 | 亚洲国产精品嫩草影院久久 | 精品午夜视频 | 黑人双渗透 | 亚洲激情综合 | 国产情侣自拍网 | 成人小视频在线观看免费 | 国产午夜免费视频 | 青草久久伊人 | 果冻传媒天美传媒在线小视频播放 | 女人张开腿让男人做爽爽 | 国产嘿咻 | 色就色欧美综合偷拍区a | 国产小青蛙 | 国外成品精品1688 | 四虎地址8848aa4hc44四虎 四虎成人永久地址 | 青青在线视频免费 | 美女班主任让我爽了一夜视频 | 美女模特被c免费视频 | 微福利92合集 | 99久久爱热6在线播放 | 操岳母逼小说 | 亚洲精品第三页 | 亚洲欧美天堂综合久久 | 2019午夜福合集高清完整版 | 成 人 亚洲 综合天堂 | 日本一区二区三区精品 | 2021国产麻豆剧传媒新片 | 精品国产美女福利在线 | 亚洲一区二区三区不卡在线播放 | 日本人护士免费xxxx视频 | 97自拍视频在线观看 | 国产小视频在线免费 | yy6080欧美三级理论 |