|
代码示例
通过以上的介绍,相信您对java的引用机制以及几种引用方式的异同已经有了一定了解。光是概念,可能过于抽象,下面我们通过一个例子来演示如何在代码中使用Reference机制。
1 String str = new String("); //①
2 ReferenceQueue<String> rq = new ReferenceQueue<String>(); //②
3 WeakReference<String> wf = new WeakReference<String>(str, rq); //③
4 str=null; //④取消"hello"对象的强引用
5 String str1=wf.get(); //⑤假如"hello"对象没有被回收,str1引用"hello"对象
6 //假如"hello"对象没有被回收,rq.poll()返回null
7 Reference<? extends String> ref=rq.poll(); //⑥
在以上代码中,注意⑤⑥两处地方。假如“hello”对象没有被回收wf.get()将返回“hello”字符串对象,rq.poll()返回null;而加入“hello”对象已经被回收了,那么wf.get()返回null,rq.poll()返回Reference对象,但是此Reference对象中已经没有str对象的引用了(PhantomReference则与WeakReference、SoftReference不同)。
引用机制与复杂数据结构的联合应用
了解了GC机制、引用机制,并配合上ReferenceQueue,我们就可以实现一些防止内存溢出的复杂数据类型。
例如,SoftReference具有构建Cache系统的特质,因此我们可以结合哈希表实现一个简单的缓存系统。这样既能保证能够尽可能多的缓存信息,又可以保证Java虚拟机不会因为内存泄露而抛出OutOfMemoryError。这种缓存机制特别适合于内存对象生命周期长,且生成内存对象的耗时比较长的情况,例如缓存列表封面图片等。对于一些生命周期较长,但是生成内存对象开销不大的情况,使用WeakReference能够达到更好的内存管理的效果。
附SoftHashmap的源码一份,相信看过之后,大家会对Reference机制的应用有更深入的理解。
1package com.***.widget;
2
3//: SoftHashMap.java
4import java.util.*;
5import java.lang.ref.*;
6
7import android.util.Log;
9public class SoftHashMap extends AbstractMap {
10 /** The internal HashMap that will hold the SoftReference. */
11 private final Map hash = new HashMap();
12 /** The number of "hard" references to hold internally. */
13 private final int HARD_SIZE;
14 /** The FIFO list of hard references, order of last access. */
15 private final LinkedList hardCache = new LinkedList();
16 /** Reference queue for cleared SoftReference objects. */
17 private ReferenceQueue queue = new ReferenceQueue();
18
19 //Strong Reference number
20 public SoftHashMap() { this(100); }
21 public SoftHashMap(int hardSize) { HARD_SIZE = hardSize; }
22
23
24 public Object get(Object key) {
25 Object result = null;
26 // We get the SoftReference represented by that key
27 SoftReference soft_ref = (SoftReference)hash.get(key);
28 if (soft_ref != null) {
29 // From the SoftReference we get the value, which can be
30 // null if it was not in the map, or it was removed in
31 // the processQueue() method defined below
32 result = soft_ref.get();
33 if (result == null) {
34 // If the value has been garbage collected, remove the
35 // entry from the HashMap.
36 hash.remove(key);
37 } else {
38 // We now add this object to the beginning of the hard
39 // reference queue. One reference can occur more than
40 // once, because lookups of the FIFO queue are slow, so
41 // we don't want to search through it each time to remove <br>< span><br><="" > 43<="" > ="" >keep recent use object in memory<="" ><br><="" > 44<="" ><="" > hardcache.addfirst(result); <br><="" > 45<="" > ="" >if<="" > (hardcache.size() <="" >><="" > hard_size) <="" span><span><br><="" > 46<="" > ="" > remove the last entry if list longer than hard_size <="" > 47<="" > hardcache.removelast(); <br><="" > 48<="" }<="" span><="" > <br><="" > 49<="" > ="" > 50<="" > ="" > 51<="" >return<="" > result; <br><="" > 52<="" > ="" > 53<="" > 54<="" **<="" > we define our own subclass of softreference which contains <br><="" > 55<="" > ="" not only the value but also the key to make it easier to find <br><="" > 56<="" the entry in the hashmap after it's been garbage collected. <="" span="">*/</br><>
57 private static class SoftValue extends SoftReference {
58 private final Object key; // always make data member final
59 /** Did you know that an outer class can access private data
60 members and methods of an inner class? I didn't know that! <br>< span><br><="" > 62<="" outer class's private information. an outer class can also </br><> 63 access private members of an inner class inside its inner
64 class. */
65 private SoftValue(Object k, Object key, ReferenceQueue q) {
66 super(k, q);
67 this.key = key;
68 }
69 }
70
71 /** Here we go through the ReferenceQueue and remove garbage
72 collected SoftValue objects from the HashMap by looking them
73 up using the SoftValue.key data member. */
74 public void processQueue() {
75 SoftValue sv;
76 while ((sv = (SoftValue)queue.poll()) != null) {
77 if(sv.get()== null){
78 Log.e(", ");
79 }else{
80 Log.e(", ");
81 }
82 hash.remove(sv.key); // we can access private data!
83 Log.e(", " + sv.key);
84 }
85 }
86 /** Here we put the key, value pair into the HashMap using
87 a SoftValue object. */
88 public Object put(Object key, Object value) {
89 processQueue(); // throw out garbage collected values first
90 Log.e(", " + key);
91 return hash.put(key, new SoftValue(value, key, queue));
92 }
93 public Object remove(Object key) {
94 processQueue(); // throw out garbage collected values first
95 return hash.remove(key);
96 }
97 public void clear() {
98 hardCache.clear();
99 processQueue(); // throw out garbage collected values
100 hash.clear();
101 }
102 public int size() {
103 processQueue(); // throw out garbage collected values first
104 return hash.size();
105 }
106 public Set entrySet() {
107 // no, no, you may NOT do that!!! GRRR
108 throw new UnsupportedOperationException();
109 }
110}
111
112
113 |
|