手动排队的弱参考状态是什么?

时间:2011-04-07 18:20:59

标签: java garbage-collection weak-references

手动将引用排入队列时对象的状态是什么?

this.s = "foo";
WeakReference<String> wr = new WeakReference<String>(this.s);
wr.enqueue();

我发现的所有文档都讨论了垃圾收集器排队对象,而不是手动执行时会发生什么。

这有什么意义吗?对象被入队的意义是什么,但仍然有可达的引用(强,弱,幻像)?

编辑:额外奖励后续问题:当物体在遥远的未来某个时间变得无法到达时,它是否会再次入队?

4 个答案:

答案 0 :(得分:2)

有一篇关于Java中引用类型的好文章: http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html

用几句话说: 你可以这样做:

public class Main {
    public static void main(String[] args) throws InterruptedException{
        String weakString = "Help me";
        ReferenceQueue<String> refQ = new ReferenceQueue<String>();
        WeakReference<String> weakRef = new WeakReference<String>(weakString, refQ);
        //there is no more "hard reference to the string"
        weakString = null;
        //there is no object in ReferenceQueue
        System.out.println(refQ.poll());
        //put the object in the ReferenceQueue
        weakRef.enqueue();
        while (true) {
            //There will be returned "Help me" until the garbage collector will "kill" 
            //"weak" string. This will be done after some time because there are no                                     
            //more strong references to the string. After that will be returned a null  
            //object.
            System.out.println(weakRef.get());
            //only one time there will be returned a refenrece to the String object
            System.out.println(refQ.poll());
            Thread.sleep(1000);
        }
    }
}

这是专为处理某种缓存而设计的。 通过这种方式,您可以确保长时间内不会在内存中存在未使用的对象。 在调用weakRef.enqueue();之后,ReferenceQueue可用于执行某种清理。例如,关闭用于处理数据的文件或流。

答案 1 :(得分:2)

强引用仍然存在,因此该对象不符合收集条件。正如JVestry指出的那样,如果使用队列创建弱引用,则wr.enqueue()会按预期返回true。

这样做的一个潜在用途是让你的处理程序能够对一个对象进行操作,该对象受到其挂起的垃圾收集或其他一些系统状态的改变,你想要采取相同的操作,就像收集对象一样,例如也许你对保存系统资源的内容保持软引用,这样系统可以处理内存不足的情况,而如果你正常完成,你仍然可以自己管理关闭资源。

关于第二个问题,引用只排队一次,无论你是使用enqueue()还是gc作为集合的一部分。

编辑重要的是要记住,参考队列之间的关系是参考,在这种情况下是wr,而不是参考,在这种情况下是s。您可以对同一个对象进行多次弱引用,并实现多个排队(排序),每个弱引用一个。但是,它是队列中的弱引用,而不是引用,尽管它应该仍然可以从弱引用中获得。有关详细信息,请参阅“通知”部分中java.lang.ref上的javadoc。

答案 2 :(得分:1)

在您的情况下,wr.enqueue()将返回false,因为您在创建WeakReference时未指定队列。如果在创建WeakReference时提供ReferenceQueue,则wr.enqueue()将返回true。

手动排列弱引用没有意义。这就像写下弱引用已经被垃圾收集而没有:'s'仍然是对“foo”的强烈引用。

答案 3 :(得分:-1)

  

有什么情况会有意义吗?

ReferenceQueues有时用于资源管理,在这种情况下调用enqueue()自己在GC运行之前释放资源是有意义的,因为一些资源相当有限(这可以在dispose()方法中完成弱的参考本身作为安全)。

添加:如果清理需要时间,这可能很有用,因为参考队列可以在自己的线程中读取,它不会挂起你的主线程。

  

对象入队是什么意思,但仍然有可达参考(强,弱,幻影)?

文档声明在对象引用设置为null后调用它,因此enqueue()不能直接影响对象状态当前文档声明enqueue调用未被使用gc,它意味着在gc执行之前对Reference进行排队。引用的对象不会受此调用的影响,但是读取引用队列的清理代码可以处理该对象使用的资源。

<强>编辑: 现在检查了1.6文档,因此使用enqueue纠正了关于gc的错误(旧的文档没有指出这一点,但是限制gc对用户代码的暴露是有意义的)