我知道每当垃圾收集器收集一个类实例时,都会调用finalize()。但是,当通过队列将一个类的实例传递给另一个线程时,我有点困惑。什么时候会在这个场景中调用我的类实例的finalize()?
比方说,这是线程1的骨架:
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()并使用其他的东西,但它会更复杂。
java方法参数最接近的C/++比较是它们是一个按值传递的指针。所以它是通过复制,但它只是指针的副本。 (唯一的操作是取消引用。)只要系统中有一个指针指向对象的位置,该位置就不会被收集。 – Affe
我强烈建议你为数据包添加一个清理方法来清理C指针,而不是依赖于finalize方法,或者甚至使用finalize方法 –