最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java Reference源碼解析

 更新時間:2017年03月21日 14:28:15   作者:Java開發(fā)-擱淺  
這篇文章主要為大家詳細解析了Java Reference源碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下

Reference對象封裝了其它對象的引用,可以和普通的對象一樣操作,在一定的限制條件下,支持和垃圾收集器的交互。即可以使用Reference對象來引用其它對象,但是最后還是會被垃圾收集器回收。程序有時候也需要在對象回收后被通知,以告知對象的可達性發(fā)生變更。 

Java提供了四種不同類型的引用,引用級別從高到低分別為FinalReference,SoftReference,WeakReference,PhantomReference。其中FinalReference不對外提供使用。每種類型對應(yīng)著不同級別的可達性。

簡介

強引用FinalReference

強引用指的是,程序中有直接可達的引用,而不需要通過任何引用對象,如Object obj = new Object();中,obj為強引用。

軟引用SoftReference

軟引用,非強引用,但是可以通過軟引用對象來訪問。軟引用的對象,只有在內(nèi)存不足的時候(拋出OOM異常前),垃圾收集器會決定回收該軟引用所指向的對象。軟引用通常用于實現(xiàn)內(nèi)存敏感的緩存。

SoftReference<Object> softRef = new SoftReference<Object>(new Object());

弱引用WeakReference

弱引用,非強引用和軟引用,但是可以通過弱引用對象來訪問。弱引用的對象,不管內(nèi)存是否足夠,只要被垃圾收集器發(fā)現(xiàn),該引用的對象就會被回收。實際的應(yīng)用見WeakHashMap等。

WeakReference<Object> weakRef = new WeakReference<Object>(new Object());

虛引用PhantomReference

虛引用,該引用必須和引用隊列(ReferenceQueue)一起使用,一般用于實現(xiàn)追蹤垃圾收集器的回收動作,比如在對象被回收的時候,會調(diào)用該對象的finalize方法,在使用虛引用可以實現(xiàn)該動作,也更加安全。

Object obj = new Object();
ReferenceQueue<Object> refQueue = new ReferenceQueue<>();
PhantomReference<Object> phantom = new PhantomReference<Object>(obj, refQueue);
ReferenceQueue

該隊列作為引用中的一員,可以和上述三種引用類型組合使用,該隊列的作用是:創(chuàng)建Reference時,將Queue注冊到Reference中,當(dāng)該Reference所引用的對象被垃圾收集器回收時,會將該Reference放到該隊列中,相當(dāng)于一種通知機制。
示例 Demo1:

ReferenceQueue queue = new ReferenceQueue();

WeakReference reference = new WeakReference(new Object(), queue);
System.out.println(reference);
System.gc();

Reference reference1 = queue.remove();
System.out.println(reference1);

源碼分析

Reference和ReferenceQueue

Reference內(nèi)部有幾個比較重要的屬性

// 用于保存對象的引用,GC會根據(jù)不同Reference來特別對待
private T referent;
// 如果需要通知機制,則保存的對對應(yīng)的隊列
ReferenceQueue<? super T> queue;
/* 這個用于實現(xiàn)一個單向循環(huán)鏈表,用以將保存需要由ReferenceHandler處理的引用 */
Reference next;

static private class Lock { };
// 鎖,用于同步pending隊列的進隊和出隊
private static Lock lock = new Lock();
// 此屬性保存一個PENDING的隊列,配合上述next一起使用
private static Reference pending = null;

狀態(tài)圖

內(nèi)部類ReferenceHandler

ReferenceHandler作為Reference的靜態(tài)內(nèi)部類,用于實現(xiàn)將pending隊列里面的Reference實例依次添加到不同的ReferenceQueue中(取決于Reference里面的queue)。該pending的元素由GC負責(zé)加入。
注:這里對pending隊列進行加鎖,個人認為是因為GC線程可能和ReferenceHandler所在的線程并發(fā)執(zhí)行,如GC采用CMS并發(fā)收集的時候。

如下代碼所示

// 此線程在靜態(tài)塊中啟動,即一旦使用了Reference,則會啟動該線程
private static class ReferenceHandler extends Thread {
  public void run() {
    for (;;) {

      Reference r;
      synchronized (lock) {
        if (pending != null) {
          r = pending;
          Reference rn = r.next;
          // 從pending中取下一個元素,如果后繼為空,則next指向自身   pending = (rn == r) ? null : rn;
          r.next = r;
        } else {
          try {
            // 沒有則等待,后續(xù)加入元素會調(diào)用lock.notify喚醒
            lock.wait();
          } catch (InterruptedException x) { }
          continue;
        }
      }
      // ...
      ReferenceQueue q = r.queue;
      // 如果該Reference注冊了對應(yīng)的Queue,則加入到該Queue中
      if (q != ReferenceQueue.NULL) q.enqueue(r);
    }
  }
}

ReferenceQueue屬性

// 用于標(biāo)識沒有注冊Queue
static ReferenceQueue NULL = new Null();
// 用于標(biāo)識已經(jīng)處于對應(yīng)的Queue中
static ReferenceQueue ENQUEUED = new Null();

static private class Lock { };
/* 互斥鎖,用于同步ReferenceHandler的enqueue和用戶線程操作的remove和poll出隊操作 */
private Lock lock = new Lock();
// 隊列
private volatile Reference<? extends T> head = null;
// 隊列中的元素個數(shù)
private long queueLength = 0;

ReferenceQueue.enqueue

只會通過Reference里要調(diào)用該方法,用于將Reference放入到當(dāng)前隊列中

boolean enqueue(Reference<? extends T> r) {
  synchronized (r) {
    // 判斷是否已經(jīng)入隊了
    if (r.queue == ENQUEUED) return false;
    synchronized (lock) {
      r.queue = ENQUEUED;
      // 單向循環(huán)
      r.next = (head == null) ? r : head;
      head = r;
      queueLength++;
      if (r instanceof FinalReference) {
        sun.misc.VM.addFinalRefCount(1);
      }
      // 通知當(dāng)前掛起的線程(調(diào)用remove時有可能會掛起)
      lock.notifyAll();
      return true;
    }
  }
}

ReferenceQueue.remove

public Reference<? extends T> remove(long timeout)
  throws IllegalArgumentException, InterruptedException
{
  if (timeout < 0) {
    throw new IllegalArgumentException("Negative timeout value");
  }
  synchronized (lock) {
    // 從隊列中取出一個元素
    Reference<? extends T> r = reallyPoll();
    // 如果不為空,則直接返回
    if (r != null) return r;
    for (;;) {
      // 否則等待,由enqueue時notify喚醒
      lock.wait(timeout);
      r = reallyPoll();
      if (r != null) return r;
      if (timeout != 0) return null;
    }
  }
}

具體執(zhí)行流程

以上述示例Demo1作為分析

// 創(chuàng)建一個引用隊列
ReferenceQueue queue = new ReferenceQueue();

// 創(chuàng)建虛引用,此時狀態(tài)為Active,并且Reference.pending為空,當(dāng)前Reference.queue = 上面創(chuàng)建的queue,并且next=null
WeakReference reference = new WeakReference(new Object(), queue);
System.out.println(reference);
// 當(dāng)GC執(zhí)行后,由于是虛引用,所以回收該object對象,并且置于pending上,此時reference的狀態(tài)為PENDING
System.gc();

/* ReferenceHandler從pending中取下該元素,并且將該元素放入到queue中,此時Reference狀態(tài)為ENQUEUED,Reference.queue = ReferenceENQUEUED */

/* 當(dāng)從queue里面取出該元素,則變?yōu)镮NACTIVE,Reference.queue = Reference.NULL */
Reference reference1 = queue.remove();
System.out.println(reference1);

應(yīng)用 - WeakHashMap

WeakHashMap在使用上和HashMap類型,都是Hash + 鏈表解決沖突,唯一不同點在于前者的Key是使用虛引用來實現(xiàn)的,即當(dāng)進行垃圾回收的時候,就是被回收掉,此時WeakHashMap會在下次操作的時候,根據(jù)被回收掉的Key,從Map里面移除掉。

Entry

當(dāng)創(chuàng)建Entry的時候,會注冊進當(dāng)前Map屬性的queue,當(dāng)key被回收后,則該Entry會被放入到queue中,每當(dāng)操作Map的時候,才會將原有的Value清除掉。(由expungeStaleEntries方法來進行,并且沒有啟動一個單獨的線程來處理,沒有必要,這樣子簡化了邏輯以及避免鎖的開銷)

// 外部WeakHashMap屬性
private final ReferenceQueue<Object> queue = new ReferenceQueue<>();

/* 這里采用了集成WeakReference而不是直接使用,是因為當(dāng)被回收的時候,具體的Key是不知道的,這里需要往WeakReference額外加入一些屬性,以便在被回收后通知時,能夠定位到具體的Key/value */
private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
  // 這里屬性不能加入key,否則會導(dǎo)致存在強引用而不能被視為WeakReference回收掉
  V value;
  int hash;
  Entry<K,V> next;
  
  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;
  }
  // ...
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 《阿里巴巴 Java開發(fā)手冊》讀后感小結(jié)

    《阿里巴巴 Java開發(fā)手冊》讀后感小結(jié)

    這篇文章主要介紹了《阿里巴巴 Java開發(fā)手冊》讀后感小結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • 關(guān)于java中構(gòu)造函數(shù)的一些知識詳解

    關(guān)于java中構(gòu)造函數(shù)的一些知識詳解

    下面小編就為大家?guī)硪黄P(guān)于java中構(gòu)造函數(shù)的一些知識詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • Java中indexOf()的用法小結(jié)

    Java中indexOf()的用法小結(jié)

    這篇文章主要介紹了Java中indexOf()的用法小結(jié),indexOf()有四種方法,用來查找某個字符或字符串的位置,本文通過示例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2024-01-01
  • Java springboot Mongodb增刪改查代碼實例

    Java springboot Mongodb增刪改查代碼實例

    這篇文章主要介紹了Java springboot Mongodb增刪改查代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • Scala入門之List使用詳解

    Scala入門之List使用詳解

    這篇文章主要介紹了Scala入門之List使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • Java并發(fā)包之CopyOnWriteArrayList類的深入講解

    Java并發(fā)包之CopyOnWriteArrayList類的深入講解

    這篇文章主要給大家介紹了關(guān)于Java并發(fā)包之CopyOnWriteArrayList類的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 利用spring boot如何快速啟動一個web項目詳解

    利用spring boot如何快速啟動一個web項目詳解

    這篇文章主要給大家介紹了關(guān)于利用spring boot如何快速啟動一個web項目的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧、
    2017-12-12
  • Mybatis下動態(tài)sql中##和$$的區(qū)別講解

    Mybatis下動態(tài)sql中##和$$的區(qū)別講解

    今天小編就為大家分享一篇關(guān)于Mybatis下動態(tài)sql中##和$$的區(qū)別講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • Java壓縮之LZW算法字典壓縮與解壓講解

    Java壓縮之LZW算法字典壓縮與解壓講解

    今天小編就為大家分享一篇關(guān)于Java壓縮之LZW算法字典壓縮與解壓講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • Java實現(xiàn)簡單抽獎功能界面

    Java實現(xiàn)簡單抽獎功能界面

    這篇文章主要為大家詳細介紹了Java實現(xiàn)簡單抽獎功能界面,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11

最新評論

河源市| 德令哈市| 上犹县| 乡宁县| 南投市| 江门市| 古浪县| 任丘市| 太保市| 北京市| 红原县| 从化市| 阜阳市| 山东省| 台江县| 红安县| 浦城县| 永丰县| 涡阳县| 屏东市| 东阳市| 旬邑县| 洪洞县| 冷水江市| 上饶市| 苏尼特左旗| 东莞市| 怀仁县| 磐安县| 得荣县| 永靖县| 土默特左旗| 城步| 临猗县| 文成县| 辽中县| 杨浦区| 瑞昌市| 平凉市| 会宁县| 大宁县|