Update 07. 消除过期的对象引用.md

This commit is contained in:
Joe 2019-02-27 11:54:11 +08:00 committed by GitHub
parent 1bf3d24d66
commit 71c6044ccf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,6 +1,5 @@
# 7. 消除过期的对象引用
---
  如果你从使用手动内存管理的语言 (如 C 或 C++) 切换到像 Java 这样的带有垃圾收集机制的语言,那么作为程序员的工作就会变得容易多了,因为你的对象在使用完毕以后就自动回收了。当你第一次体验它的时候,它就像魔法一样。这很容易让人觉得你不需要考虑内存管理,但这并不完全正确。
@ -63,9 +62,9 @@ public Object pop() {
  一般来说,**当一个类自己管理内存时,程序员应该警惕内存泄漏问题。** 每当一个元素被释放时,元素中包含的任何对象引用都应该被清除。
  **另一个常见的内存泄漏来源是缓存。**一旦将对象引用放入缓存中很容易忘记它的存在并且在它变得无关紧要之后仍然保留在缓存中。对于这个问题有几种解决方案。如果你正好想实现了一个缓存只要在缓存之外存在对某个项entry的键key引用那么这项就是明确有关联的就可以用 `WeakHashMap` 来表示缓存这些项在过期之后自动删除。记住只有当缓存中某个项的生命周期是由外部引用到键key而不是值value决定时`WeakHashMap` 才有用。
  **另一个常见的内存泄漏来源是缓存。** 一旦将对象引用放入缓存中很容易忘记它的存在并且在它变得无关紧要之后仍然保留在缓存中。对于这个问题有几种解决方案。如果你正好想实现了一个缓存只要在缓存之外存在对某个项entry的键key引用那么这项就是明确有关联的就可以用 `WeakHashMap` 来表示缓存这些项在过期之后自动删除。记住只有当缓存中某个项的生命周期是由外部引用到键key而不是值value决定时`WeakHashMap` 才有用。
  更常见的情况是,缓存项有用的生命周期不太明确,随着时间的推移一些项变得越来越没有价值。在这种情况下,缓存应该偶尔清理掉已经废弃的项。这可以通过一个后台线程 (也许是 `ScheduledThreadPoolExecutor`) 或将新的项添加到缓存时顺便清理。Link`此处输入代码`edHashMap 类使用它的 `removeEldestEntry` 方法实现了后一种方案。对于更复杂的缓存,可能直接需要使用 `java.lang.ref`
  更常见的情况是,缓存项有用的生命周期不太明确,随着时间的推移一些项变得越来越没有价值。在这种情况下,缓存应该偶尔清理掉已经废弃的项。这可以通过一个后台线程 (也许是 `ScheduledThreadPoolExecutor`) 或将新的项添加到缓存时顺便清理。`LinkedHashMap` 类使用它的 `removeEldestEntry` 方法实现了后一种方案。对于更复杂的缓存,可能直接需要使用 `java.lang.ref`
  第三个常见的内存泄漏来源是监听器和其他回调。如果你实现了一个 API其客户端注册回调但是没有显式地撤销注册回调除非采取一些操作否则它们将会累积。确保回调是垃圾收集的一种方法是只存储弱引用weak references例如仅将它们保存在 `WeakHashMap` 的键key中。