• 4中引用(强,软,弱,虚)侧重弱引用


    1,强引用,对象有强引用与之关联,即使在内存不足,抛出OutOfMemory错误也不会回收这种对象
    
    2,软引用是用来描述一些有用但并不是必需的对象,java.lang.ref.SoftReference类来表示。
       对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象。可以很好地用来解决OOM的问题,适合用来实现缓存:比如网页缓存、图片缓存等。
       软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被JVM回收,这个软引用就会被加入到与之关联的引用队列中。
    
    3,弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。
    在java中,用java.lang.ref.WeakReference类来表示。 弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被JVM回收,就会被加入到与之关联的引用队列中。
    4,虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期。在java中用java.lang.ref.PhantomReference类表示。 如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。 注意的是,虚引用必须和引用队列关联使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之 关联的引用队列中。 弱引用和虚引用的区别是:虚引用总是存在的,只是看存在地方的。而若引用如果没有队列与关联,那么垃圾回收就会没了。如何有关联队列那么两者就一样了。

    说说WeakReference弱引用

    Java弱引用(WeakReference)的理解与使用

    侧重说下弱引用:因为ThreadLocal用到了弱引用,而线程局部变量被广泛的应用在各种框架中。

    了解如何定义和使用:

    public class Car
    {
        private double     price;
        private String    color;
        
        public Car(double price, String color)
        {
            this.price = price;
            this.color = color;
        }
    public class WeakReferenceCar extends WeakReference<Car>
    {
        public WeakReferenceCar(Car car)
        {
            super(car);
        }
    }
    Car car = new Car(2000.0, "red");
    WeakReferenceCar wrc = new WeakReferenceCar(car);

    当gc执行:WeakReferenceCar关联的对象Car被回收掉了。

    值得注意的是car本身是有强引用的(xxx=new xxx()):

    public static void main(String[] args) {
            
            Car car = new Car(22000,"silver");
            WeakReference<Car> weakCar = new WeakReference<Car>(car);        
            int i=0;        
            while(true){
                if(weakCar.get()!=null){
                    i++;
                    System.out.println("Object is alive for "+i+" loops - "+weakCar);
                }else{
                    System.out.println("Object has been collected.");
                    break;
                }
            }

     即使有 car 引用指向对象, 且 car 是一个strong reference, weakCar指向的对象仍然被回收了.

    这是因为java的编译器在发现进入while循环之后, car 已经没有被使用了。

    而如果后面有使用是不会被回收的比如下面:

            Car car = new Car(22000,"silver");
            WeakReference<Car> weakCar = new WeakReference<Car>(car);        
            int i=0;        
            while(true){
                System.out.println("here is the strong reference 'car' "+car);
                if(weakCar.get()!=null){
                    i++;
                    System.out.println("Object is alive for "+i+" loops - "+weakCar);
                }else{
                    System.out.println("Object has been collected.");
                    break;
                }
            }

    总结:

    1,一个变量(在方法类创建的)是否被回收,看方法是否执行完,一般都被回收的。
       但是如果赋值给了其他全局变量,那么是不会被回收的。
    
    2,是否是强引用,一般是不会被回收,但是如果后面没有使用,也是会被回收的。
    
    3,是否是弱引用,一般gc执行就会被回收,
    但是如果有强引用关联,那么是不会被回收的, 但是出现第2点的情况,也就是后面不被使用了,也是会被回收的
    (其实有强引用关联也就当作强引用的情况在处理了)

    补充:对于强引用是否需要手动置空?以便让gc回收。

    Object c = new Car();
    c=null;

    其实是不需要的,手动置空对象对于程序员来说, 是一件繁琐且违背自动回收的理念的.  

    因为在java中, 对于简单对象, 当调用它的方法执行完毕后, 指向它的引用会被从stack中popup, 所以他就能在下一次GC执行时被回收了

    最后一个问题:缓存用哪个引用?

    很多人觉得用软引用更好,内存不够再回收。

    个人觉得不可以:

    据说内存不够时候,清理过程中程序会被挂起,这样很不友好。

    而一般启动清理机制,应该是内存使用到达一定程度(应该是可以设置),程序还可以继续执行。

    补充:上面的某些说法应该是不确切的:(或者不完整,因为逻辑上不通)

    当创建一个对象,用强引用,然后通过传参变成弱引用对象。如果说弱引用对象有被强引用关联那么就是强引用处理,这样弱引用就毫无意义了(不符合逻辑)。

    个人理解是:只有非创建时,被强引用,(也就是创建后在别的地方被引用了)才会当作强引用处理。

  • 相关阅读:
    离线安装 Cloudera Manager 5 和 CDH5.10
    Sersync+Rsync实现触发式文件同步
    Azkaban3.x集群部署(multiple executor mode)
    内置函数
    递归
    嵌套函数,匿名函数,高阶函数
    局部变量,全局变量,作用域
    函数的介绍
    文件处理
    第二模块-三元运算
  • 原文地址:https://www.cnblogs.com/straybirds/p/8314115.html
Copyright © 2020-2023  润新知