国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java Reference源碼解析

Java Reference源碼解析

2020-08-31 14:31Java開發-擱淺 Java教程

這篇文章主要為大家詳細解析了Java Reference源碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下

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

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

簡介

強引用FinalReference

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

軟引用SoftReference

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

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

弱引用WeakReference

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

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

虛引用PhantomReference

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

?
1
2
3
4
Object obj = new Object();
ReferenceQueue<Object> refQueue = new ReferenceQueue<>();
PhantomReference<Object> phantom = new PhantomReference<Object>(obj, refQueue);
ReferenceQueue

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

?
1
2
3
4
5
6
7
8
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內部有幾個比較重要的屬性

?
1
2
3
4
5
6
7
8
9
10
11
12
// 用于保存對象的引用,GC會根據不同Reference來特別對待
private T referent;
// 如果需要通知機制,則保存的對對應的隊列
ReferenceQueue<? super T> queue;
/* 這個用于實現一個單向循環鏈表,用以將保存需要由ReferenceHandler處理的引用 */
Reference next;
 
static private class Lock { };
// 鎖,用于同步pending隊列的進隊和出隊
private static Lock lock = new Lock();
// 此屬性保存一個PENDING的隊列,配合上述next一起使用
private static Reference pending = null;

狀態圖

Java Reference源碼解析

內部類ReferenceHandler

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

如下代碼所示

?
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
// 此線程在靜態塊中啟動,即一旦使用了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 {
            // 沒有則等待,后續加入元素會調用lock.notify喚醒
            lock.wait();
          } catch (InterruptedException x) { }
          continue;
        }
      }
      // ...
      ReferenceQueue q = r.queue;
      // 如果該Reference注冊了對應的Queue,則加入到該Queue中
      if (q != ReferenceQueue.NULL) q.enqueue(r);
    }
  }
}

ReferenceQueue屬性

?
1
2
3
4
5
6
7
8
9
10
11
12
// 用于標識沒有注冊Queue
static ReferenceQueue NULL = new Null();
// 用于標識已經處于對應的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;
// 隊列中的元素個數
private long queueLength = 0;

ReferenceQueue.enqueue

只會通過Reference里要調用該方法,用于將Reference放入到當前隊列中

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
boolean enqueue(Reference<? extends T> r) {
  synchronized (r) {
    // 判斷是否已經入隊了
    if (r.queue == ENQUEUED) return false;
    synchronized (lock) {
      r.queue = ENQUEUED;
      // 單向循環
      r.next = (head == null) ? r : head;
      head = r;
      queueLength++;
      if (r instanceof FinalReference) {
        sun.misc.VM.addFinalRefCount(1);
      }
      // 通知當前掛起的線程(調用remove時有可能會掛起)
      lock.notifyAll();
      return true;
    }
  }
}

ReferenceQueue.remove

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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;
    }
  }
}

具體執行流程

以上述示例Demo1作為分析

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 創建一個引用隊列
ReferenceQueue queue = new ReferenceQueue();
 
// 創建虛引用,此時狀態為Active,并且Reference.pending為空,當前Reference.queue = 上面創建的queue,并且next=null
WeakReference reference = new WeakReference(new Object(), queue);
System.out.println(reference);
// 當GC執行后,由于是虛引用,所以回收該object對象,并且置于pending上,此時reference的狀態為PENDING
System.gc();
 
/* ReferenceHandler從pending中取下該元素,并且將該元素放入到queue中,此時Reference狀態為ENQUEUED,Reference.queue = ReferenceENQUEUED */
 
/* 當從queue里面取出該元素,則變為INACTIVE,Reference.queue = Reference.NULL */
Reference reference1 = queue.remove();
System.out.println(reference1);

應用 - WeakHashMap

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

Entry

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 外部WeakHashMap屬性
private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
 
/* 這里采用了集成WeakReference而不是直接使用,是因為當被回收的時候,具體的Key是不知道的,這里需要往WeakReference額外加入一些屬性,以便在被回收后通知時,能夠定位到具體的Key/value */
private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
  // 這里屬性不能加入key,否則會導致存在強引用而不能被視為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;
  }
  // ...
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国产精品天天干 | 国产精品毛片一区二区三区 | 日韩av一区二区在线观看 | 一级中文字幕 | 成人午夜视频免费 | 中文字幕免费看 | 大桥未久亚洲精品久久久强制中出 | 高清xxxx| 久久免费的视频 | 国产淫片 | 欧美日韩国产一区二区三区在线观看 | 欧美综合一区二区三区 | 女人久久久久久久 | 国产片在线看 | 国产亚洲精品精品国产亚洲综合 | 国产亚洲一区二区三区在线观看 | 综合网日韩 | 亚洲欧美日韩在线一区 | 亚洲激情精品 | 狠狠干天天干 | 色婷婷av久久久久久久 | 91精品国产综合久久久久久丝袜 | av在线播放网站 | 一区不卡| 色花av| 亚洲国产欧美在线 | 日韩精品区 | 成年人精品视频 | 国产做a爰片久久毛片a我的朋友 | 久久久久av | 国产精品久久久久久久久小说 | 久草热8精品视频在线观看 毛片黄片免费观看 | 成人免费大片黄在线播放 | 亚洲免费一区 | 亚洲精品免费在线观看 | 亚洲精品系列 | 免费精品视频 | 国产成人精品免费视频大全最热 | 国产中文视频 | 美女视频一区二区三区 | 精品成人av一区二区在线播放 |