什么是软引用?

  • Post category:Java

软引用(SoftReference)是Java中一种比较特殊的引用类型,如同弱引用(WeakReference)、虚引用(PhantomReference)一样,都是为了解决Java中的内存不足问题而出现的。

与弱引用相比,软引用的生命周期稍微长一些。软引用所指向的对象在内存中并不是一定存在的,但是如果内存空间足够,垃圾回收器就不会回收它所指向的对象。当JVM内存不足时,软引用指向的对象才会被垃圾回收器回收。

SoftReference类继承了Reference类,可以通过get()方法获得引用所指向的对象,当对象被回收后,该方法返回null。

使用场景:

在一些需要缓存数据的场合,可以使用软引用来缓存对象,当缓存对象过多时,jvm扫描到软引用对象时会及时回收相应的缓存对象,以获得更多内存空间。

示例一:

import java.lang.ref.SoftReference;
public class SoftReferenceTest {
    public static void main(String[] args) {
        // 创建一个字符串对象
        String str = new String("www.baidu.com");
        // 创建一个软引用,指向刚刚创建的字符串对象
        SoftReference<String> sr = new SoftReference<String>(str);
        // 把刚刚创建的字符串对象变成null
        str = null;
        System.gc();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 通过软引用获取字符串对象
        System.out.println(sr.get());
    }
}

输出结果:www.baidu.com

示例二:

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;

public class SoftReferencesInHashMap {

    public static void main(String[] args) {
        Map<String, SoftReference<StringBuffer>> map = new HashMap<String, SoftReference<StringBuffer>>();
        for (int i=0; i<100; i++) {
            String key = Integer.toString(i);
            StringBuffer value = new StringBuffer("Value_" + i);
            map.put(key, new SoftReference<StringBuffer>(value));
        }

        for (int i=0; i<1000; i++) {
            String key = Integer.toString(i % 100);
            if (map.get(key) == null) {
                System.out.println("Not found: " + key);
            }
            else {
                StringBuffer string = map.get(key).get();
                if (string == null) {
                    System.out.println("Object is null: " + key);
                }
                else {
                    System.out.println("String Buffer for " + key + ": " + string);
                }
            }
        }
    }
}

在该示例中,我们创建了一个HashMap,使用软引用将字符串对象缓存起来。然后,我们循环1000次从HashMap中获取字符串对象,直到JVM内存不足时,HashMap中的字符串对象才会被垃圾回收器回收。每次获取字符串对象时,程序判断该对象是否为null,以此判断该对象是否已被回收。如果对象不为null,则输出该对象的值。这样,我们就可以通过软引用实现对于大量数据的缓存,且不会对JVM内存造成大量的负担。