注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

写着玩

Bob

 
 
 

日志

 
 
 
 

关于引用  

2008-12-23 18:18:44|  分类: Java |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

 

强引用

首先,我们得从强引用开始,强引用是JAVA的普通的引用,你每天都使用的种类,比如代码:

StringBuffer buffer = new StringBuffer();

创建一个 new StringBuffer()并存储在变量buffer中的一个强引用。市的,这是小儿科,但请耐心听我说。强引用的重要部分—使他们强的部分是—他们与垃圾回收器如何相互影响。特别的,假如一个对象是通过强引用链表可到达的(强的可到达)。GC是没有资格收集的。因为你不想GC销毁你继续使用的对象。这正是你所希望的。

当强引用太强了

应用程序使用不能进行适度扩展的类并不罕见。这个类可能仅仅是简单的使用了final或者是更加复杂的情况比如通过工厂类返回未知数量的实例。比如你使用类Widget,不管什么原因都无法扩展Widget以增加一个新的方法。

当你需要跟踪这个对象的扩展信息会发生什么呢?这样,加入我们发现我们需要跟踪每个Widget的serial number,但是Widget类实际不存在serial number的属性—并且以你为Widget是不可以扩展的,我们不能加入一个。根本没有问题,使用HashMaps:

serialNumberMap.put(widget, widgetSerialNumber);

从表面上看一切都很好,但是widget的强引用几乎可以确定产生了问题。我们必须知道(100%确定)什么时候Widget的serial number是不需要了,我们好从map中删除。否则就会产生内存泄露(在需要删除的时候没有删除)或者发现我们的丢失了serial number(假如删除了正在使用的Widget)。假如这个问题听起来很熟悉,他们应该是:使用非垃圾收集语言的用户面对管理内存的确切问题

另外一个常见的强引用问题是(缓存)caching,特别是大结构比如图像。比如你有一个程序必须和用户提供的图像一起工作,象我做的网站设计工具一样,自然的你希望缓存这些图片,因为从硬盘读取它们很慢而且要避免这些图片在内存中存在两个一样的拷贝。

因为图像缓存应该避免载入我们不需要的图片,因此你很快意识到缓存总是应该包括一个在内存中任何图片的引用---普通的强引用。虽然这个引用会强制把图片保留在内存中,但是你需要有一个方法检测什么时候图片不在需要并且从缓存中删除,以致变成了GC的职责。再次的你被迫复制GC的行为和手工检测一个对象是否应该在内存中。

弱引用

弱引用,简单的说,是一个没有强到要强制把一个对象保留在内存中的引用。弱引用允许你利用GC的能力为你检测可到达的,因此你不再需要自己去做,创建一个弱引用:

WeakFeference weakWidget = new WeakReference(widget);

然后你可以在你代码的其他地方使用weakWidget.get()获得实际的Widget对象。当然弱引用没有强到可以阻止GC, 因此你可能发现weakWidget.get()突然返回null。

为了解决早先提到的widget serial number问题,原来是使用WeakHashMap类,WeakHashMap非常类似HashMap,除了健值是指向弱引用。假如一个WeakHashMap的健值不可用了,他的词条将被自动删除。这避免了我描述的不可以预见的错误。

引用队列

当一个弱引用返回null,他所指向的对象已经变成了垃圾并且这个弱引用对象也几乎没有价值了。这意味着需要某种清理;比如WeakHashMap,需要删除无用的词条以避免不断增加的已死的WeakReference。

不同程度的弱引用

至此,我们都只是提及弱引用,但是事实上,有四种不同程度的引用,按照从强到弱的顺序:强、软、弱、虚(phantom幽灵?)。我们已经讨论了强和弱引用,因此让我们看一下另外两个。

软引用

软引用非常类似弱引用,除了他所指向的对象没那么快被回收以外。一个只有弱引用可以到达的对象将在下一个GC周期被丢弃,但是一个软引用对象可能还会在逗留一会。

软引用不必弱引用需要更多的动作,但是在实际情况中,软引用可到达的对象只要内存足够通常会一直保留在内存中。这使得他是一个非常优秀的缓存基础,象上面提到的图像缓存。因为你可以让GC去关心什么样的可到达对象以及什么样的情况需要回收。

虚引用

虚引用完全不同于软引用和弱引用。他们控制他们的对象是如此的微弱以甚至不能或得对象---get()方法总是返回null。他只被用于跟踪被放入引用队列,那样你知道对象已经死了。和弱引用的区别:当对象变成弱引用可到达得时候弱引用立刻被放入了饮用队列,这发生在finalization或发生垃圾回收之前;理论上,这个对象可能会复活,但是弱引用仍然保留死的状态。虚引用是在对象在物理上被删除出内存时才放入队列的。她的get()方法总是返回null以阻止一个几乎已经死了的对象的复活。

那虚引用有什么好处呢?我只知道两种情况:首先,他们允许你检测对象对删除的确切时间。事实上这也是唯一的方法。他不是总有用,但是在特定的情况下迟早有用比如维护大的图像:假如你知道一幅图像确切应该被回收,你可以在尝试载入下一副图像之前等待。因此不用担心

OutOfMemoryError

第二,虚引用避免了一个基本问题可以通过

finalization

finalize

()方法能够通过呢我一个强引用而复活一个对象。

  评论这张
 
阅读(134)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017