(一) 查看API文档,WeakHashmap要点如下:

1. 以弱键 实现的基于哈希表的 Map。在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。丢弃某个键时,其条目从映射中有效地移除

2. WeakHashMap 类的行为部分取决于垃圾回收器的动作。因为垃圾回收器在任何时候都可能丢弃键,WeakHashMap 就像是一个被悄悄移除条目的未知线程。特别地,即使对 WeakHashMap 实例进行同步,并且没有调用任何赋值方法,在一段时间后 size 方法也可能返回较小的值,对于 isEmpty 方法,返回 false,然后返回true,对于给定的键,containsKey 方法返回 true 然后返回 false,对于给定的键,get 方法返回一个值,但接着返回 null,对于以前出现在映射中的键,put
方法返回 null,而 remove 方法返回 false,对于键 set、值 collection 和条目 set 进行的检查,生成的元素数量越来越少。

3. WeakHashMap 中的每个键对象间接地存储为一个弱引用的指示对象。因此,不管是在映射内还是在映射之外,只有在垃圾回收器清除某个键的弱引用之后,该键才会自动移除。

(二) 引用对象的四种分类:

Api图片如下:

1. 强引用(Strong Reference)

2. 弱引用(Weak Reference)

3. 软引用(Soft Reference)

4. 幻象引用(Phantom Reference)

(三) 深入理解

至此,对于WeakHashMap有了一个基本概念,但是还是比较模糊。找到一篇英文文档,将要点总结如下(如有翻译不对,请指出,谢谢):

1. 强引用

强引用就是普通的Java引用,代码:

  1. StringBuffer buffer = new StringBuffer();

这句代码创建了一个StringBuffer对象,在变量buffer中存储了这个对象的一个强引用。强引用之所以称之为“强”(Strong),是因为他们与垃圾回收器(garbage collector)交互的方式。特别是(specifically),如果一个对象通过强引用连接(strongly reachable-强引用可到达),那么它就不在垃圾回收期处理之列。当你正在使用某个对象而不希望垃圾回收期销毁这个对象时,强引用通常正好能满足你所要的。

2. 当强引用太强的时候

假定你要使用一个final类Widget,但是基于某种原因,你不能继承(extend)这个类或者通过其他方法为这个类增加一些新的功能。如果你需要跟踪(track)这个类的不同对象的序列号。那么可以将这些对象放入HashMap中,获得不同的value值,这样就可以做到通过不同的value值跟踪这些对象了。代码:

  1. serialNumberMap.put(widget, widgetSerialNumber);

但是widget的强引用会产生一些问题。在我们不需要一个Widget的序列号时,我们需要将这个Widget对应的Entry从HashMap中移除。否则我们可能面临内存泄露(memory leak)的问题(如果我们没有在应当移除Widgt的时候移除它),或者我们将莫名其妙的丢失序列号(如果我们正在使用Widget时却移除了它)。如果这些问题类似,那么这些问题是无垃圾回收机制(non-garbage-collected language)的编程语言的开发者所面临的问题。Java的开发者不需要担心这种问题。

W:如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它。当内存空 间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。

强引用的另外一个常见问题就是图片缓存(cache)。普通的强引用将使得Image继续保存在内存中。在一些情况下,我们不需要有些Image继续留在内存中,我们需要将这些图片从内存中移出,这时,我们将扮演垃圾回收期的角色来决定哪些照片被移除。使这些被移出的图片被垃圾回收器销毁。下一次,你被迫再次扮演垃圾回收期的角色,手动决定哪些Image被回收。

Note:我觉得也可以用对象的hashCode来跟踪对象。作者在此所举的例子,只在说明Strong Reference。

3. 弱引用

简单说,就是弱引用不足以将其连接的对象强制保存在内存中。弱引用能够影响(leverage)垃圾回收器的某个对象的可到达级别。代码:

  1. WeakReference<Widget> weakWidget = new WeakReference<Widget>(widget);

你可以使用weakWidget.get()方法老获取实际的强引用对象。但是在之后,有可能突然返回null值(如果没有其他的强引用在Widget之上),因为这个弱引用被回收。其中包装的Widget也被回收。

解决Widget序列号的问题,最简单的方法就是使用WeakHashmap。其key值为弱引用。如果一个WeakHashmap的key变成垃圾,那么它对应用的value也自动的被移除。

W:垃圾回收期并不会总在第一次就找到弱引用,而是会找几次才能找到。

4. 引用队列(Reference Quene)

一旦弱引用返回null值,那么其指向的对象(即Widget)就变成了垃圾,这个弱引用对象(即weakWidget)也就没有用了。这通常意味着要进行一定方式的清理(cleanup)。例如,WeakHashmap将会移除一些死的(dread)的entry,避免持有过多死的弱引用。

ReferenceQuene能够轻易的追踪这些死掉的弱引用。可以讲ReferenceQuene传入WeakHashmap的构造方法(constructor)中,这样,一旦这个弱引用指向的对象成为垃圾,这个弱引用将加入ReferenceQuene中。

如下图所示:

5. 软引用

除了在抛出自己所指向的对象的迫切程度方面不一样之外,软引用和弱引用基本一样。一个对象为弱可到达(或者指向这个对象的强引用是一个弱引用对象-即强引用的弱引用封装),这个对象将在一个垃圾回收循环内被丢弃。但是,弱引用对象会保留一段时间之后才会被丢弃。

软引用的执行和弱引用并没有任何不同。但是,在供应充足(in plentiful supply)的情况下,软可到达对象将在内存中保存尽可能长的时间。这使得他们在内存中有绝佳的存在基础(即有尽可能长存在的基础)。因为你让垃圾回收器去担心两件事情,一件是这个对象的可到达性,一件是垃圾回收期多么想要这些对象正在消耗的内存。

6. 幻象引用(phantom reference)

幻象引用于弱引用和软引用均不同。它控制其指向的对象非常弱(tenuous),以至于它不能获得这个对象。get()方法通常情况下返回的是null值。它唯一的作用就是跟踪列队在ReferenceQuene中的已经死去的对象。

幻象引用和弱引用的不同在于其入队(enquene)进入ReferenceQuene的方式。当弱引用的对象成为若可到达时,弱引用即列队进入ReferenceQuene。这个入队发生在终结(finialize)和垃圾回收实际发生之前。理论上,通过不正规(unorthodox)的finilize()方法,成为垃圾的对象能重新复活(resurrected),但是弱引用仍然是死的。幻象引用只有当对象在物理上从内存中移出时,才会入队。这就阻止我们重新恢复将死的对象。

W:终结(Finalization)指比拉圾回收更一般的概念,可以回收对象所占有的任意资源,比如文件描述符和图形上下文等。

幻象引用由两个好处:

A:它能确定某一个对象从内存中移除的时间,这也是唯一的方式。通常情况下,这不是非常有用。但是迟早(come in handy)会用到手动处理大图片的情况:如果你确定一张图片需要被垃圾回收,那么在你尝试加载下一张照片前,你应该等待这张照片被回收完成。这样就使得令人恐惧的(dreaded)内存溢出不太可能发生。

B:虚幻引用能够避终结(finilize)的基本问题。finilize()方法能够通过给一个垃圾对象关联一个强引用使之复活。问题是覆写了finilize()方法的对象在成为垃圾之前,为了回收,垃圾回收期需要执行两次单独的循环。第一轮循环确定某个对象是垃圾,那么它就符合终结finilize的条件。在finilize的过程中,这个对象可能被“复活”。在这个对象被实际移除之前,垃圾回收期不得不重新运行一遍。因为finilization并不是实时调用的,所以在终止进行的过程中,可能发生了gc的多次循环。在实际清理垃圾对象时,这导致了一些延时滞后。这将导致Heap中有大量的垃圾导致内存溢出。

幻象引用不可能发生以上的情况,当幻象引用入队时,它实际上已经被移除了内存。幻象内存无法“复活”对象。这发现这个对象时虚幻可到达时,在第一轮循环中,它就被回收。

可以证明,finilize()方法从不在第一种情况下使用,但是虚幻引用提供了一种更安全和有效的使用和被排除掉的finilize方法的机制,使得垃圾回收更加简单。但是因为有太多的东西需要实现,我通常不适用finilize。

W:Object类中相关内容如下:

文档中相关内容如下:

(四) 原文地址及其他翻译

原文地址:http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html

其他翻译地址:http://blog.csdn.net/fancyerii/article/details/5610360

深入理解WeakHashmap的更多相关文章

  1. java弱引用之WeakHashMap相关资料

    本人博客中有一篇文章对java中的引用有详细的介绍[http://www.cnblogs.com/javaee6/p/4763190.html],java中WeakHashMap这个类就是java弱引 ...

  2. WeakHashMap和HashMap的区别

    看Java源码的时候,看到了 WeakHashMap ,我一直以来使用的 都是 HashMap,于是查了一下两者的区别 (一) 查看API文档,WeakHashmap要点如下: 1. 以弱键 实现的基 ...

  3. 5.9 j(java学习笔记)强软弱虚引用及WeakHashMap、IdentityHashMap、EnumMap

    一.引用分类 强:运行垃圾回收机制后也不回收,程序出现内存溢出也不回收. 软:在垃圾回收机制运行时判断内存是否已满,如果内存已满则回收,内存充足则不回收. 弱:垃圾回收机制运行后不论内存是否充足都会立 ...

  4. 基础-WeakReference

    一.概述 为了更好的理解WeakHashMap的原理,我们有必要先来了解一下WeakReference的作用及实现原理.Java中有一个专门的包java.lang.ref,里面定义了我们通常所说的几种 ...

  5. Java常用集合类详解

    在Java中有一套设计优良的接口和类组成了Java集合框架,使程序员操作成批的数据或对象元素极为方便.所有的Java集合都在java.util包中. 在编写程序的过程中,使用到集合类,要根据不同的需求 ...

  6. 收藏的技术文章链接(ubuntu,python,android等)

    我的收藏 他山之石,可以攻玉 转载请注明出处:https://ahangchen.gitbooks.io/windy-afternoon/content/ 开发过程中收藏在Chrome书签栏里的技术文 ...

  7. Java中关于WeakReference和WeakHashMap的理解

    新美大的10月11日的笔试中有一道选择题,让选择函数返回结果,代码如下: private static String test(){ String a = new String("a&quo ...

  8. WeakHashMap回收时机结合JVM 虚拟机GC的一些理解

    一直很想知道WeakHashMap的使用场景,想来想去只能用在高速缓存中,而且缓存的数据还不是特别重要,因为key(key不存在被引用的时候)随时会被回收 所以研究了一下WeakHashMap的回收时 ...

  9. 【转】Java中关于WeakReference和WeakHashMap的理解

    新美大的10月11日的笔试中有一道选择题,让选择函数返回结果,代码如下: private static String test(){ String a = new String("a&quo ...

随机推荐

  1. ci框架——文章查看之上篇下篇

    1:从数据库查询出推荐的文章的信息,循环查出每篇推荐文章的id和title; foreach($data as $val){ $dataid[]=$val->aid; $datatitle[]= ...

  2. Day 10 Linux nfs && crond(摘)

    (摘) 介绍: NFS 是Network File System的缩写,即网络文件系统.一种使用于分散式文件系统的协定,由Sun公司开发,于1984年向外公布.功能是通过网络让不同的机器.不同的操作系 ...

  3. 微信小程序项目结构

  4. 洛谷—— P2656 采蘑菇

    https://www.luogu.org/problem/show?pid=2656 题目描述 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连 ...

  5. 枚举型变量 ErrorStatus HSEStartUpStatus及使用

    ErrorStatus和C语言中的int .char一样,后面定义的HSEStartUpStatus是这个变量.举例,你的ErrorStatus 代表bool类型的0或者1. typedef enum ...

  6. Chrome 浏览器安装Vue插件方法 (十分详细)

    博主最近在研究Vue,无奈新手想安装Chrome的Vue插件,整理下安装流程: 1.首先去github下载vue.zip文件插件(还有npm安装方法这里就不介绍了自行百度)下载地址:https://g ...

  7. Limitations of Forms Personalization (文档 ID 420518.1)

    In this Document   Purpose   Scope   Details   Diagnostics & Utilities Community:   References A ...

  8. BUPT复试专题—中序遍历序列(2013)

    题目描述 给出一个序列,判断该序列是不是某二叉搜索树的中序遍历序列,如果是输出"Yes",否则输出"No".一颗带权二叉树是一颗二叉搜索树(二叉排序树),当且仅 ...

  9. Exactly-once Spark Streaming from Apache Kafka

    这篇文章我已经看过两遍了.收获颇多,抽个时间翻译下,先贴个原文链接吧.也给自己留个任务 http://blog.cloudera.com/blog/2015/03/exactly-once-spark ...

  10. 关于Java基础的一些笔试题总结

    针对近期腾讯.京东.网易等公司的笔试,遇到一些有关Java基础的问题,在此总结,希望能通过这几道经典问题题发散,举一反三,借此打牢基础!自己总结,望提出宝贵意见! 一.关于null的一道小题  先开开 ...