欢迎来到皮皮网网首页

【安乡捉麻雀源码】【扑克联盟源码】【uwp app 源码】softreference源码

来源:完美视界影视源码 时间:2024-11-23 16:59:54

1.java三个引用类型

softreference源码

java三个引用类型

       å››ç§å¼•ç”¨ç±»åž‹

       æ‰€ä»¥åœ¨ JDK.1.2 之后,Java 对引用的概念进行了扩充,将引用分为了:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4 种,这 4 种引用的强度依次减弱。

       ä¸€ï¼Œå¼ºå¼•ç”¨

       Java中默认声明的就是强引用,比如:

       Object obj = new Object(); //只要obj还指向Object对象,Object对象就不会被回收

       obj = null; //手动置null

       åªè¦å¼ºå¼•ç”¨å­˜åœ¨ï¼Œåžƒåœ¾å›žæ”¶å™¨å°†æ°¸è¿œä¸ä¼šå›žæ”¶è¢«å¼•ç”¨çš„对象,哪怕内存不足时,JVM也会直接抛出OutOfMemoryError,不会去回收。如果想中断强引用与对象之间的联系,可以显示的将强引用赋值为null,这样一来,JVM就可以适时的回收对象了

       äºŒï¼Œè½¯å¼•ç”¨

       è½¯å¼•ç”¨æ˜¯ç”¨æ¥æè¿°ä¸€äº›éžå¿…需但仍有用的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等。

       åœ¨ JDK1.2 之后,用java.lang.ref.SoftReference类来表示软引用。

       ä¸‹é¢ä»¥ä¸€ä¸ªä¾‹å­æ¥è¿›ä¸€æ­¥è¯´æ˜Žå¼ºå¼•ç”¨å’Œè½¯å¼•ç”¨çš„区别:

       åœ¨è¿è¡Œä¸‹é¢çš„Java代码之前,需要先配置参数 -Xms2M -Xmx3M,将 JVM 的初始内存设为2M,最大可用内存为 3M。

       é¦–先先来测试一下强引用,在限制了 JVM 内存的前提下,下面的代码运行正常

       public class TestOOM {

        public static void main(String[] args) {

        testStrongReference();

        }

        private static void testStrongReference() {

        // 当 new byte为 1M 时,程序运行正常

        byte[] buff = new byte[ * * 1];

        }

       }

       ä½†æ˜¯å¦‚果我们将

       byte[] buff = new byte[ * * 1];

       æ›¿æ¢ä¸ºåˆ›å»ºä¸€ä¸ªå¤§å°ä¸º 2M 的字节数组

       byte[] buff = new byte[ * * 2];

       åˆ™å†…存不够使用,程序直接报错,强引用并不会被回收

       æŽ¥ç€æ¥çœ‹ä¸€ä¸‹è½¯å¼•ç”¨ä¼šæœ‰ä»€ä¹ˆä¸ä¸€æ ·ï¼Œåœ¨ä¸‹é¢çš„示例中连续创建了 个大小为 1M 的字节数组,并赋值给了软引用,然后循环遍历将这些对象打印出来。

       public class TestOOM {

        private static List<Object> list = new ArrayList<>();

        public static void main(String[] args) {

        testSoftReference();

        }

        private static void testSoftReference() {

        for (int i = 0; i < ; i++) {

        byte[] buff = new byte[ * ];

        SoftReference<byte[]> sr = new SoftReference<>(buff);

        list.add(sr);

        }

        System.gc(); //主动通知垃圾回收

        for(int i=0; i < list.size(); i++){

        Object obj = ((SoftReference) list.get(i)).get();

        System.out.println(obj);

        }

        }

       }

       æ‰“印结果:

       æˆ‘们发现无论循环创建多少个软引用对象,打印结果总是只有最后一个对象被保留,其他的obj全都被置空回收了。

       è¿™é‡Œå°±è¯´æ˜Žäº†åœ¨å†…存不足的情况下,软引用将会被自动回收。

       å€¼å¾—注意的一点 ,安乡捉麻雀源码 即使有 byte[] buff 引用指向对象, 且 buff 是一个strong reference, 但是 SoftReference sr 指向的对象仍然被回收了,这是因为Java的编译器发现了在之后的代码中, buff 已经没有被使用了, 所以自动进行了优化。

       å¦‚果我们将上面示例稍微修改一下:

        private static void testSoftReference() {

        byte[] buff = null;

        for (int i = 0; i < ; i++) {

        buff = new byte[ * ];

        SoftReference<byte[]> sr = new SoftReference<>(buff);

        list.add(sr);

        }

        System.gc(); //主动通知垃圾回收

        for(int i=0; i < list.size(); i++){

        Object obj = ((SoftReference) list.get(i)).get();

        System.out.println(obj);

        }

        System.out.println("buff: " + buff.toString());

        }

       åˆ™ buff 会因为强引用的存在,而无法被垃圾回收,从而抛出OOM的错误。

       å¦‚果一个对象惟一剩下的引用是软引用,那么该对象是软可及的(softly reachable)。垃圾收集器并不像其收集弱可及的对象一样尽量地收集软可及的对象,相反,它只在真正 “需要” 内存时才收集软可及的对象。

       ä¸‰ï¼Œå¼±å¼•ç”¨

       å¼±å¼•ç”¨çš„引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收。在 JDK1.2 之后,用 java.lang.ref.WeakReference 来表示弱引用。

       æˆ‘们以与软引用同样的方式来测试一下弱引用:

        private static void testWeakReference() {

        for (int i = 0; i < ; i++) {

        byte[] buff = new byte[ * ];

        WeakReference<byte[]> sr = new WeakReference<>(buff);

        list.add(sr);

        }

        System.gc(); //主动通知垃圾回收

        for(int i=0; i < list.size(); i++){

        Object obj = ((WeakReference) list.get(i)).get();

        System.out.println(obj);

        }

        }

       æ‰“印结果:

       å¯ä»¥å‘现所有被弱引用关联的对象都被垃圾回收了。

       å››ï¼Œè™šå¼•ç”¨

       è™šå¼•ç”¨æ˜¯æœ€å¼±çš„一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,它随时可能会被回收,在 JDK1.2 之后,用 PhantomReference 类来表示,通过查看这个类的源码,发现它只有一个构造函数和一个 get() 方法,而且它的 get() 方法仅仅是返回一个null,也就是说将永远无法通过虚引用来获取对象,虚引用必须要和 ReferenceQueue 引用队列一起使用。

       public class PhantomReference<T> extends Reference<T> {

        /

**

        * Returns this reference object's referent. Because the referent of a

        * phantom reference is always inaccessible, this method always returns

        * <code>null</code>.

       

*

        * @return <code>null</code>

        */

        public T get() {

        return null;

        }

        public PhantomReference(T referent, ReferenceQueue<? super T> q) {

        super(referent, q);

        }

       }

       é‚£ä¹ˆä¼ å…¥å®ƒçš„构造方法中的 ReferenceQueue 又是如何使用的呢?

       äº”,引用队列(ReferenceQueue)

       å¼•ç”¨é˜Ÿåˆ—可以与软引用、弱引用以及虚引用一起配合使用,当垃圾回收器准备回收一个对象时,如果发现它还有引用,那么就会在回收对象之前,把这个引用加入到与之关联的引用队列中去。程序可以通过判断引用队列中是否已经加入了引用,来判断被引用的对象是否将要被垃圾回收,这样就可以在对象被回收之前采取一些必要的措施。