java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > 浅析WeakHashMap

浅析Java中的WeakHashMap

作者:洞之蝉

这篇文章主要介绍了浅析Java中的WeakHashMap,WeakHashMap其实和HashMap大多数行为是一样的,只是WeakHashMap不会阻止GC回收key对象,那么WeakHashMap是怎么做到的呢,这就是我们研究的主要问题,需要的朋友可以参考下

WeakHashMap

在Java或者是Android编程中,我们一般都会使用到Map,比如HashMap这样的具体实现。更高级一点,我们可能会使用WeakHashMap。

WeakHashMap其实和HashMap大多数行为是一样的,只是WeakHashMap不会阻止GC回收key对象(不是value),那么WeakHashMap是怎么做到的呢,这就是我们研究的主要问题。

在开始WeakHashMap之前,我们先要对弱引用有一定的了解。

在Java中,有四种引用类型

这其中还有一个概念叫做引用队列(Reference Queue)

WeakHashMap如何不阻止对象回收呢 

private static final class Entry<K, V> extends WeakReference<K> implements
Map.Entry<K, V> {
int hash;
boolean isNull;
V value;
Entry<K, V> next;
interface Type<R, K, V> {
R get(Map.Entry<K, V> entry);
}
Entry(K key, V object, ReferenceQueue<K> queue) {
super(key, queue);
isNull = key == null;
hash = isNull ? 0 : key.hashCode();
value = object;
}

如源码所示,

如何删除被回收的key数据呢

在Javadoc中关于WeakHashMap有这样的描述,当key不再引用时,其对应的key/value也会被移除。

那么是如何移除的呢,这里我们通常有两种假设策略

而WeakHashMap采用的是轮询的形式,在其put/get/size等方法调用的时候都会预先调用一个poll的方法,来检查并删除失效的Entry

void poll() {
Entry<K, V> toRemove;
while ((toRemove = (Entry<K, V>) referenceQueue.poll()) != null) {
removeEntry(toRemove);
Log.d(LOGTAG, "removeEntry=" + toRemove.value);
}
}

为什么没有使用看似更好的通知呢,我想是因为在Java中没有一个可靠的通知回调,比如大家常说的finalize方法,其实也不是标准的,不同的JVM可以实现不同,甚至是不调用这个方法。

当然除了单纯的看源码,进行合理的验证是检验分析正确的一个重要方法。

这里首先,我们定义一个MyObject类,处理一下finalize方法(在我的测试机上可以正常调用,仅仅做为辅助验证手段)

class MyObject(val id: String) : Any() {
protected fun finalize() {
Log.i("MainActivity", "Object($id) finalize method is called")
}
}

然后是调用者的代码,如下

private val weakHashMap = WeakHashMap<Any, Int>()
var count : Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
dumpWeakInfo()
fab.setOnClickListener { view ->
//System.gc()// this seldom works use Android studio force gc stop
weakHashMap.put(MyObject(count.toString()), count)
count ++
dumpWeakInfo()
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
}
fun dumpWeakInfo() {
Log.i("MainActivity", "dumpWeakInfo weakInfo.size=${weakHashMap.size}")
}

我们按照如下操作

I/MainActivity(10202): dumpWeakInfo weakInfo.size=1
I/MainActivity(10202): dumpWeakInfo weakInfo.size=2
I/MainActivity(10202): dumpWeakInfo weakInfo.size=3
I/MainActivity(10202): Object(2) finalize method is called
I/MainActivity(10202): Object(1) finalize method is called
I/MainActivity(10202): Object(0) finalize method is called
I/WeakHashMap(10202): removeEntry=2
I/WeakHashMap(10202): removeEntry=0
I/WeakHashMap(10202): removeEntry=1
I/MainActivity(10202): dumpWeakInfo weakInfo.size=1

注意:System.gc()并不一定可以工作,建议使用Android Studio的Force GC

到此这篇关于浅析Java中的WeakHashMap的文章就介绍到这了,更多相关浅析WeakHashMap内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文