2

我知道每当垃圾收集器收集类实例时都会调用 finalize() 。但是,当通过队列将类的实例传递给另一个线程时,我有点困惑。

假设这是 Thread1 的骨架:

for(i=0; i<1000; i++) {
   Packet pkt = new Packet();  // instance of class
   pkt.id = i;
   thread2.queue.put(pkt);
}

然后,线程 2 将从队列中删除数据包并执行冗长的操作。这第二个线程是否获得了数据包的“副本”,还是通过某种形式的引用?重要的是,如果是通过复制,在线程 1 中创建的实例上的 finalize() 可以在线程 2 完成数据包之前调用。如果是通过引用,我保证 finalize() 只为数据包中的信息调用一次。

这个基本示例可能没有显示重要性,但我在数据包中存储了一个 C 指针(来自 JNI),以便在我完成对象时破坏一些内存。如果它通过副本传递,则内存可能会在第二个线程完成之前被破坏。如果它是通过引用传递的,那么它应该只在 GC 看到它不再被两个线程使用时才被销毁(我想要的行为)。如果不能保证后一种情况,我不会使用 finalize() 并使用其他东西,但它会更复杂。

4

1 回答 1

6

第二个线程接收相同的实际对象实例。您可以避免过早完成。

如果您想以这种方式考虑,它会接收对象引用的副本。

此外,finalize当垃圾收集器发现对象已变成垃圾时,不一定会运行它——VM 可以在以后的任何时间自由运行它,并在此之后的某个时间实际回收内存。你真的不能依赖什么时候finalize运行。但是,由于您关心的是知道在第二个线程完成对象之前finalize 不会调用它,所以这无关紧要。但值得知道!

于 2011-07-21T15:58:07.560 回答