JAVA里面四种引用以及如何使用软引用构建高速缓存

1. 四种引用

1.强引用

我们在程序里面大部分创建的都是强引用。强引用的对象如果在可达性分析之后依然有引用链存在,那么程序即使内存溢出也不会回收这个对象。必须下面的代码创建的就是强引用对象

Object a = new Object();

2.软引用

String string= "";
SoftReference<String> softReference = new SoftReference<String>(string);
string = softRefence.get();

软引用对象的生命力相比强引用弱了一些。如果发现一个对象只被一个软引用引用的话,那么JVM在即将内存溢出的时候会回首这个对象,通过软引用获取到对象需要使用get方法获取,如果对象被回收的话,使用get方法返回去的值就位null。

3.弱引用

 WeakReference<Man> weak=new WeakReference<Man>(new Man());
 man = weak.get();

弱引用的对象就相对来说更弱一下,如果一个对象只被弱引用引用的话,那么每次垃圾回收的时候都会把这个对象回收掉。
通过弱引用获取到对象需要使用get方法获取,如果对象被回收的话,使用get方法返回去的值就位null。

4.虚引用

PhantomReference<String> pa = new PhantomReference<String>("S",referenceQueueStr);

虚引用对象生命力基本没有,因为即使构造完一个虚引用,无论对象是否被回收。那么你使用get()方法也无法获取到虚引用指向的对象。虚引用一般只是用来监视对象是否被回收,监视的方式就是我的我们下面要讲的引用队列。

5.引用队列ReferenceQueue

在软引用,弱引用,虚引用的构造函数都有一个引用队列的参数,只不过虚引用时必须的参数,其他的两个引用里面是可选的。它的作用就是一旦一个对象被回收,那么这个对象的虚引用对象就会被放进这个引用队列里面。听起来很别扭?代码来看

   public static void main(String[] args) throws InterruptedException {
        ReferenceQueue<Man> referenceQueue= new ReferenceQueue<Man>();
        WeakReference<Man> weak=new WeakReference<Man>(new Man(),referenceQueue);
        System.out.println("man对应的虚引用对象:"+weak.hashCode());
        System.gc();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("垃圾回收后 man"+weak.get());
        System.out.println("引用队列里面的对象"+referenceQueue.poll().hashCode());
    	}

运行结果

man对应的虚引用对象:1450495309
垃圾回收后 mannull
引用队列里面的对象1450495309

通过上面的代码验证大家可以看出来,因为new Man()这个对象没有任何强引用,只有一个虚引用。所以在垃圾回收的时候把这个对象回收了,然后把它的虚引用对象加入到了引用队列里面。通过hash值相等大家可以看出了,同样的弱引用对象在垃圾回收之后被加入到了引用队列。大家可以自己试验一下软引用也是同样的结果。但是测试软引用需要启动是设置堆的大小小一点测试起来更方便。引用队列的源代码大家可以看一下,他就是一个类似于链表的结构,每个节点通过前后节点进行存储的。

2.使用软引用构建缓存

程序里面最快的缓存就是直接在内存里面构建缓存。但是如果我们使用强引用构建缓存的话,一旦缓存过大无法回收就会导致内存溢出。这个时候我么可以使用软引用构建缓存。构建缓存的思路也很简单,就是把需要存储的单个数据使用软引用引用,用Map存储,键值可以为对象的一个唯一标识,key值为弱引用对象。这样一旦程序内存不够用的时候,就会清除一部分软引用。这个时候我们就没有办法通过map里面的软引用获取到实际对象了。这样既需要我们手动去清除map里面已经被回收的对象的软引用对象,判断的方式就是引用队列。
下面是我构建的一个简单软引用缓存代码

@Data
public class Man {

    private String name;

    private Integer  age;

    private Integer id;

}
public class ManCache {

    private static  ManReference manReference;

    private static  ReferenceQueue<Man> referenceReferenceQueue;

    private static ConcurrentHashMap<Integer,ManReference> cacheMap;

    private ManCache (){
        referenceReferenceQueue = new ReferenceQueue<Man>();
    }
    private static class ManCacheSingle{
        static  ManCache manCache = new ManCache();
    }

    public static ManCache getManCahce(){
        return ManCacheSingle.manCache;
    }
    public  static void   cacheInto(Man man){
        cacheClean();
        int id = man.getId();
        ManReference manReference = new ManReference(man);
        cacheMap.put(id,manReference);
    }

    public  static  void cacheClean(){
        ManReference manReference;
        //如果对象被回收,那么就把这个对象在map里面对应的值删除
        while ((manReference=(ManReference) referenceReferenceQueue.poll())==null){
            int id = manReference.id;
            cacheMap.remove(id);
        }
    }

    public static Man getMan (Integer id)throws RuntimeException{
        check(id);
        Man man = cacheMap.get(id).get();
        if( man==null ){
            man = getFromDatabase(id);
            cacheInto(man);
        }
        return man;
    }



    private static class ManReference extends SoftReference<Man> {
        int id;
        public ManReference(Man referent) {
            super(referent,referenceReferenceQueue);
            id=referent.getId();
        }
    }



    private static void check(Integer id){
        if(id==null){
            throw  new RuntimeException("id不可以为null");
        }
    }

    /**
     *   数据库取值
     * @return
     * @param id
     */
    private static Man  getFromDatabase(Integer id){
           return  new Man();
    }

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值