美文网首页
四种引用类型的学习记录

四种引用类型的学习记录

作者: 132xin | 来源:发表于2020-07-20 15:48 被阅读0次

四种引用的对比

类型 回收机制 用途 生存时间
强引用 从不回收 对象的状态 JVM停止运行时
软引用 内存不足时回收 缓存 内存不足时
弱引用 对象没有被引用时回收 缓存 对象回收时
虚引用 对象被回收时 管理精准控制内存的稳定性 未知

强引用

强引用时平时我们最经常用的一种引用,例如直接new一个对象。

 String str=new String();

强引用具有如下的特点:

  • 即使发生OOM也不不会发生回收
  • 强引用可以直接使用目标对象
  • 强引用在引用对象null时会导致内存泄漏

软引用

A a=new A();
SoftReference reference=new SortReference(a);

一个对象只有软引用时,内存足够时,则不会被回收,当内存不够时被回收,只有内存不足的时候才会回收软引用。需要注意的时在使用的时候要判断软引用对象是否为空。

软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

  ReferenceQueue queue = new  ReferenceQueue();
    SoftReference  softReference=new  SoftReference(a, queue);

Android中的例子

  • 缓存图片的时候可以使用软引用缓存,当我们获取图片的时候可以通过HashMap进行缓存,下次获取的时候直接通过key来获取,这个时候我们可以使用软引用,这样可以防止内存不足时发生OOM。
private Map<String,SoftReference> softReferenceMap=new HashMap<>();
 
 
    /**
     *
     * @param path
     */
    public  void addBitmap(String path){
        // 强引用的Bitmap对象
        Bitmap bitmap = BitmapFactory.decodeFile(path);
        // 软引用的Bitmap对象
        SoftReference<Bitmap> softBitmap = new SoftReference<Bitmap>(bitmap);
        // 添加softBitmap到Map中使其缓存
        softReferenceMap.put(path, softBitmap);
    }
 
    /**
     *
     * @param path
     * @return
     */
    public Bitmap getBitmap(String path) {
        // 从缓存中取软引用的Bitmap对象
        SoftReference<Bitmap> softBitmap = softReferenceMap.get(path);
        // 判断是否存在软引用
        if (softBitmap == null) {
            return null;
        }
        // 取出Bitmap对象,如果由于内存不足Bitmap被回收,将取得空
        Bitmap bitmap = softBitmap.get();
        return bitmap;
    }

  • 在加载过大的图片的时候可以使用软引用,但是要注意的是在使用的时候要判断一个是否为空。

public class SoftReferenceActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ImageView imageView=new ImageView(this);
        BitmapFactory.Options options=new BitmapFactory.Options();
        options.inPreferredConfig= Bitmap.Config.ARGB_4444;
        options.inPurgeable= true;
        options.inInputShareable= true;
        options.outWidth= 720;
        options.outHeight= 1280;
        Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher_round,options);
        Drawable drawable=new BitmapDrawable(getResources(),bitmap);
        SoftReference<Drawable> drawableSoftReference =
                new SoftReference<Drawable>(drawable);
        if(drawableSoftReference != null) {
            //内存不足将不显示
            imageView.setBackground(drawableSoftReference.get());
        }
 
    }
}

弱引用

A a=new A();
WeakReference<A> reference=new WeakReference<>(a);

特点:

如果一个对象只具有弱引用的时候,当垃圾回收线程扫描到之后,内存无论是否足够,都进行回收。
弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

Android中的例子

当我们使用Handler执行异步耗时任务的时候,如果我们的Activty关闭时,此时应该要回收Activity对象的,但是因为Handler持有Activity的引用,就会导致OOM
解决办法:

  • 在Activity关闭的地方将线程停止以及把Handler的消息队列的所有消息对象移除
  • 将Handler改为静态内部类,但是因为静态内部类不持有外部类的引用,所以我们可以通过弱引用的方式。
public class WeakReferenceActivity extends AppCompatActivity {
 
    private WeakReference<WeakReferenceActivity> reference;
    private MyHandler myHandler = new MyHandler(this);
 
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myHandler.sendEmptyMessage(1);
    }
 
 
    public static class MyHandler extends Handler {
        private WeakReference<WeakReferenceActivity> reference;
 
        public MyHandler(WeakReferenceActivity activity) {
            reference = new WeakReference<WeakReferenceActivity>(activity);
        }
 
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    WeakReferenceActivity weakReferenceActivity = (WeakReferenceActivity) reference.get();
                    if (weakReferenceActivity != null) {
                        System.out.print("WeakReferenceActivity");
                    }
                    break;
 
                default:
                    break;
            }
        }
    }
 
    @Override
    protected void onDestroy() {
        super.onDestroy();
        myHandler.removeCallbacksAndMessages(null);
    }
}

虚引用

作用就是跟踪对象合适被回收,但是必须要和引用队列 (ReferenceQueue)联合使用。当垃圾回收机制准备回收一个对象的时候,如果发现这个对象还存在一个虚引用,就会在这个对象被回收之前将这个虚引用加入到引用队列中,如果在引用队列中发现虚引用,那么就说明与之关联的对象将要被回收了。

参考链接:

java 软引用、弱引用、强引用、虚引用的解析

Java/Android中的强引用、软引用、弱引用、虚引用

相关文章

网友评论

      本文标题:四种引用类型的学习记录

      本文链接:https://www.haomeiwen.com/subject/qrkrkktx.html