java中的SoftReference,应用其实现缓存

Cache.java 其中MAX_REF_SIZE指示存储多少引用后需要执行clean(),可以根据应用和虚拟机情况来设置,这里假设是1m的堆大小

 1 import java.lang.ref.ReferenceQueue;
 2 import java.lang.ref.SoftReference;
 3 import java.util.concurrent.ConcurrentHashMap;
 4 
 5 public abstract class Cache<X, T extends Cacheable<X>> {
 6     /**
 7      * Define how to initiate a T according to X.
 8      * */
 9     public abstract T init(X key);
10     public static final int MAX_REF_SIZE = 6000;
11     
12     public Cache() {
13         refMap = new ConcurrentHashMap<X,MyRef>();
14         refQueue = new ReferenceQueue<T>();
15     }
16     
17     private class MyRef extends SoftReference<T>{
18 
19         private X id;
20         public MyRef(T o, ReferenceQueue<T> q) {
21             super(o, q);
22             this.id = o.cacheID();
23         }
24         
25     }
26     private ConcurrentHashMap<X,MyRef> refMap;
27     private ReferenceQueue<T> refQueue;
28     
29     public void add(T o) {
30         if(refMap.size()>MAX_REF_SIZE) {
31             clean();
32         }
33         MyRef r = new MyRef(o, refQueue);
34         refMap.put(r.id, r);
35     }
36     
37     public T get(X key) {
38         MyRef r = refMap.get(key);
39         if(r!=null) {//if there are key and object in the cache
40             T o = r.get();
41             if(o!=null)
42                 return o;
43         }
44         T o = init(key);//else execute init()
45         this.add(o);
46         return o;
47     }
48     
49     @SuppressWarnings("unchecked")
50     public void clean() {
51 //        new Thread() {
52 //            public void run() {
53                 MyRef r = null;
54                 while((r=(MyRef) refQueue.poll())!=null) {
55                     refMap.remove(r.id);
56                 }
57                 System.out.println(refMap.size());
58 //            }
59 //        }.start();
60     }
61     
62     public void clear() {
63         refMap.clear();
64         System.gc();
65         System.runFinalization();
66     }
67 }

Cacheable.java 泛型为该类的ID,该类需要能够根据ID生成对应对象

1 public interface Cacheable<X> {
2     X cacheID();
3 }

Test.java 测试类。运行参数:-Xmx1m -Xms1m

 1 public class Test {
 2 
 3     public static void main(String[] args) {
 4         Service s = new Service();
 5         Cache<Long, Person> c = new Cache<Long, Person>() {
 6 
 7             @Override
 8             public Person init(Long key) {
 9                 return s.getPerson(key);
10             }
11             
12         };
13         
14         for(long i = 0;;i++) {
15             c.add(s.getPerson(i));
16         }
17         
18     }
19     
20 }
21 class Service {
22     public Person getPerson(long id){
23         Person p = new Person();
24         p.setId(id);
25         return p;
26     }
27 }
28 class Person implements Cacheable<Long> {
29     
30     private long id;
31     private String name;
32     private boolean sex;
33     private int age;
34 
35     @Override
36     public Long cacheID() {
37         return id;
38     }
39 
40     public long getId() {
41         return id;
42     }
43 
44     public void setId(long id) {
45         this.id = id;
46     }
47 
48     public String getName() {
49         return name;
50     }
51 
52     public void setName(String name) {
53         this.name = name;
54     }
55 
56     public boolean isSex() {
57         return sex;
58     }
59 
60     public void setSex(boolean sex) {
61         this.sex = sex;
62     }
63 
64     public int getAge() {
65         return age;
66     }
67 
68     public void setAge(int age) {
69         this.age = age;
70     }
71 }

 

posted @ 2016-08-22 11:41  Kharenah  阅读(866)  评论(0编辑  收藏  举报