1

我在算法课程中浏览了队列实现的代码,并观察了作者使用的dequeue()代码:

private Node first, last;

private class Node {
    String item;
    Node next;
}

public boolean isEmpty() {
    return first == null;
}

// Code segment in doubt
public String dequeue() {
    String item = first.item;
    first = first.next;
    if (isEmpty()) last = null;
    return item;
}

在这里,firstlast可以理解地分别指向队列中的第一个和最后一个元素。我对作者使用的dequeue()中的代码有点怀疑。因为,他只是在做:

first = first.next;

没有将first.next分配给null。会不会留下会阻碍 JVM 垃圾回收机制的悬空引用(或游荡)?我有点困惑,dequeue()的代码不应该是这样的吗?(我确定在 C/C++ 中代码应该如下所示,但想知道在这种情况下 JAVA 的预期行为)

public String dequeue() {
    Node old;
    old = first;
    first = first.next;
    old.next = null;
    if (isEmpty()) last = null;
    return old.item;
}

如果有人可以向我指出一个资源,该资源通过很好的示例详细介绍了该主题,我也将不胜感激。

4

4 回答 4

2

设置old.next = null是不必要的,因为old已准备好进行垃圾收集(first = first.next分配消除了它的最后一个活动引用(一旦dequeue退出)),因此垃圾收集器不会跟踪它的任何引用。

于 2013-05-20T15:47:01.150 回答
1

假设您在队列中有 2 个对象:A 和 B

first指向Afirst.next指向B(换句话说A.next == B

唯一的参考AQueue#first变量。当你这样做

first = first.next; // first == B

没有人引用A对象了,所以它有资格进行垃圾收集。

于 2013-05-20T15:47:49.040 回答
0

只有来自活动对象的引用才重要。这些决定了哪些对象是活动的。

如果一个对象引用了一个活动对象,但它没有被引用,那么它将被收集。(JVM 不使用引用计数,无需更新)

如果两个对象相互引用(但没有其他对象),则另一种情况与人们有关。这也很好,因为只有可以从根节点(例如线程)访问的对象被保留,其他所有内容都被收集。

于 2013-05-20T16:03:11.763 回答
0

如果您的 Queue 未实现为 a Doubly Queue(意味着您可以访问队列中的 .Next 和 .Prev ),那么在设置first为 be之后first.next,将没有引用或指针first,然后垃圾收集线程将知道它(first)需要进行垃圾收集(相关内存将被释放)。

于 2013-05-20T15:47:57.447 回答