java中的软引用和弱引用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Alecor/article/details/80459578

在java 中除了基本数据类型之外,其他都是引用数据类型,而引用数据类型又分类四种

强引用

指向通过new得到的内存空间的引用叫做强引用,比如 String a = new String(“123”),其中的a就是一个强引用,它指向了一块内存为123的堆空间。平时我们用的最多的也是强类型.

软引用

软引用(在java 中可以用SoftReference类实现)的含义是,如果一个 对象 具有软引用,如果虚拟机内存不足或发生oom之前,JVM虚拟机会回收这些被软引用指向的内存区域,如果内存足够,便不会回收。一般用于存放较为敏感的信息。

弱引用

弱引用和软引用较为相识(通过WeakReference类实现),他们的区别在于,垃圾回收器一旦发现某块内存上有且仅有弱引用(一定要注意只有弱引用,没有强引用)指向这块内存的地址空间,不管当前内存是否足够,这这块被弱引用指向的内存空间都会GC回收。

虚引用

虚引用也叫幻象引用,通过PhantomReference类来实现,无法通过虚引用访问对象的任何属性和函数,虚引用只是提供了了一种确保对象在finalize以后可以做某些事情的机制。(目前学习阶段没接触到如何使用它,以后碰到了再补充一篇)

下面我们看看这软引用和弱引用之间的区别

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

/**
 * 引用区别
 *
 * @author koala
 * @date 2018/5/26
 */

public class ReferenceDemo {


    public static void main(String[] args) {

        /**
        *   str 指向堆内存内容为abc的地址
        */
        String str = new String("abc");
        // 软引用
        SoftReference<String> softReference = new  SoftReference<String>(str);

        str = null;
        System.gc();
        System.out.println(softReference.get());   // 执行结果: abc 



        String abc = new String("123");
        // 弱引用
        WeakReference<String> weekReference = new  WeakReference<String>(abc);
        // 去掉强引用
        abc = null;
        System.gc();
        System.out.println(weekReference.get());  // 执行结果: null
    }

}

,一般软软引用可以做一些缓存处理,如果不使用第三方缓存机制,可以使用软引用实现缓存方案,比如,文章缓存(从软引用里面去取文章内容,如果没有再从数据库中取,在刷回到软引用中)

我们来使用WeakHashMap来了解弱引用的使用场景

“`
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;

/**
* 弱引用对象
*
* @author koala
* @date 2018/5/26
*/

public class WeekHashMapDemo {

public static void main(String[] args) {

    /**
     *  // 假设堆空间为1000  A
     *
     *  a -> A
     *
     */

    String a = new String("ABC");

    /**
     *   // 假设堆空间为2000  B
     *
     *  b -> B
     *
     */
    String b = new String("123");

    Map weakMap = new WeakHashMap();
    Map map = new HashMap(10);

    /**
     *          a  - >  A       -- 强引用
     *   map:(AAA)  - > A         -- 强引用
     *
     *          b  - > B        -- 强引用
     *   map: (BBB)  - > B        -- 强引用
     */

    map.put(a,"AAA");
    map.put(b,"BBB");

    /**
     *          a  - >  A       -- 强引用
     *   map:(AAA)  - > A         -- 强引用
     *   weakmap:(aaa) -> A        -- 弱引用
     *
     *          b  - > B        -- 强引用
     *   map: (BBB)  - > B        -- 强引用
     *   weakmap:(bbb) -> B       -- 弱引用
     */
    weakMap.put(a,"aaa");
    weakMap.put(b,"bbb");

    /**
     *          a  - >  A       -- 强引用
     *   weakmap:aaa -> A        -- 弱引用
     *
     *          b  - > B        -- 强引用
     *   map: BBB  - > B        -- 强引用
     *   weakmap:bbb -> B       -- 弱引用
     */
    map.remove(a);

    /**
     *   weakmap:aaa -> A        -- 弱引用
     *
     *   map: BBB  - > B        -- 强引用
     *   weakmap:bbb -> B       -- 弱引用
     */
    a = null;
    b = null;

    System.gc();

    /**
     * 输出结果
     *  map,123:BBB
     *
     *  分析, 在gc之前,map集合a引用已经被移除,只有一个b引用是一个强类型
     */

    System.out.println(a);
    Iterator i = map.entrySet().iterator();
    while (i.hasNext()){
        Map.Entry en = (Map.Entry) i.next();
        System.out.println("map,"+en.getKey()+":"+en.getValue());
    }

    /**
     * 输出结果
     * weakmap,123:bbb
     *
     * 分析:weakmap集合key值为a的引用(指向地址A)是一个弱引用,gc会回收被弱引用所引用的对象,所以A地址空间会被回收(A地址中只有被弱引用引用)
     *      weakmap集合key值为b的引用,由于在map集合中有强引用指向地址B,及时weakmap中key值为b弱引用,指向这个地址空间,此地址空间也不会被回收
     *
     */
    Iterator j = weakMap.entrySet().iterator();
    while (j.hasNext()){
        Map.Entry en = (Map.Entry) j.next();
        System.out.println("weakmap,"+en.getKey()+":"+en.getValue());
    }

}

}

无论是软引用还是弱引用获取虚引用都可以使用引用队列ReferenceQueue配合使用,可以通过程序判断是否加入了某些引用,那些引用被回收了,从而我们可以在引用回收之前采取一些程序行动

猜你喜欢

转载自blog.csdn.net/Alecor/article/details/80459578