Reference ReferenceQueue WeakHashMap详解

[b]强引用[/b]
Object o = new Object();
o就是一个强引用, 强引用不会被VM GC, 即使内存不够抛出OutOfMemoryError也不会被回收

[b]软引用[/b]
/**对象不可达之后,一直到内存不足时,才被回收*/

public class SoftReference<T> extends Reference<T> {...}

[b]弱引用[/b]
/**对象不可达之后,gc运行就会被回收*/

public class WeakReference<T> extends Reference<T> {...}

[b]虚引用[/b]
/**还没搞懂,构造的时候必须传一个ReferenceQueue*/

public class PhantomReference<T> extends Reference<T> {
...
public T get() {//但是PhantomReference的get方法,无论何时都返回的是null,这个接下来在看,,,多了怕记不住
return null;
}
}


[b]还有[/b]WeakHashMap,之后再加上

Reference本身是一个链表的数据结构,有如下两个字段

private T referent;
Reference next;


Reference中 有个 静态的 pending字段

private static Reference pending = null;

vm会将不可达的Reference对象挂在pending链表上(VM实现);

Reference中还有个 ReferenceHandler 这个handler(Thread[Daemon线程]),
在一个静态快中初始化,
功能就是循环的访问pending,将pending中的不可达对象 入队(enqueue);

Reference & ReferenceQueue的关系:
Reference存在一个ReferenceQueue的引用,Reference存在一个ReferenceQueue的引用是在Reference的构造方法中初始化的,
如果没有指定,会传入一个全局默认的queue但是这个默认的queue,但是这个queue 没有实际的入队操作(见下面源码),
如果传入一个构造的queue,不可达的对象会入队(enqueue)

class ReferenceQueue<T>{
//有两个静态的ReferenceQueue
static ReferenceQueue NULL = new Null();//默认的ReferenceQueue
static ReferenceQueue ENQUEUED = new Null();
private static class Null extends ReferenceQueue {
boolean enqueue(Reference r) {//Null 的enqueue()没有实际的入队操作
return false;
}
}

boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
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);
}
lock.notifyAll();
return true;
}
}
}
}


public abstract class Reference<T>{
...
private T referent;//构造函数传入(具体的对象)

ReferenceQueue<? super T> queue;

/*(网上看来的):pending是由jvm来赋值的,
当Reference内部的referent对象的可达状态改变时,
jvm会将Reference对象放入pending链表*/
private static Reference pending = null; /* used by VM */
...
/*守护线程,将注册在queue上,
不可达的referent(pending Reference 链表)放入 queue中*/
private static class ReferenceHandler extends Thread{

ReferenceHandler(ThreadGroup g, String name) {
super(g, name);
}
public void run() {
for (;;) {//对pending的访问
...
}
}

static { //初始化守护线程:ReferenceHandler
ThreadGroup tg = Thread.currentThread().getThreadGroup();
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent());
Thread handler = new ReferenceHandler(tg, "Reference Handler");
/* If there were a special system-only priority greater than
* MAX_PRIORITY, it would be used here
*/
handler.setPriority(Thread.MAX_PRIORITY);
handler.setDaemon(true);
handler.start();
}
/**
* Adds this reference object to the queue with which it is registered,
* if any.*/
public boolean enqueue() {
return this.queue.enqueue(this);
}
...
}

[size=large][color=red][b]接下来是WeakHashMap[/b][/color][/size]

public class WeakHashMap<K,V> extends AbstractMap<K,V> implements Map<K,V> {
....
/*在WeakHashMap则在内部提供了一个非NULL的ReferenceQueue*/
/*WeakHashMap的实现也是通过ReferenceQueue这个“监听器”来实现自动删除那些引用不可达的key的*/
private final ReferenceQueue<Object> queue = new ReferenceQueue<>();

/*内部类,实体,继承WeakReference,重要的是构造方法*/
private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
V value;
int hash;
Entry<K,V> next;
Entry(Object key, V value,ReferenceQueue<Object> queue,
int hash, Entry<K,V> next) {
/*把key放入 WeakReference 的 private T referent;
WeakHashMap的key会被回收,但是value却不会被回收,
但是 通过调用 expungeStaleEntries(),value会被回收
源码如下*/
super(key, queue);
this.value = value;
this.hash = hash;
this.next = next;
}
....
}

/*核心的方法*/
private void expungeStaleEntries() {
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;
// Must not null out e.next;
// stale entries may be in use by a HashIterator
e.value = null; // Help GC
size--;
break;
}
prev = p;
p = next;
}
}
}
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值