デモコード:
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class Main {
public static void main(String[] args) throws InterruptedException {
Object test = new Object();
ReferenceQueue<Object> q = new ReferenceQueue<Object>();
PhantomReference<Object> p = new PhantomReference<Object>(test, q);
Object lock = new Object();
while (true) {
synchronized (lock) {
//q.poll() is null always,why?
if (q.poll() != null) {
break;
}
//System.gc();
lock.wait();
}
}
System.out.println(1111111);
}
}
コードをテストしましたが、常にデッド ループです。コード (System.out.println(1111111);) は実行できません。q.poll() は null を返します。
テスト オブジェクトが GC によって削除された場合、q.poll() は p オブジェクトを返し、ループを中断すると思いますが、このデモ コードを呼び出すと、私の考えとは異なります。
編集済み: デモ コードを変更しました。現在は動作します。
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class Main {
public static void main(String[] args) throws InterruptedException {
Object test = new Object();
ReferenceQueue<Object> q = new ReferenceQueue<Object>();
PhantomReference<Object> p = new PhantomReference<Object>(test, q);
Object lock = new Object();
while (true) {
synchronized (lock) {
if (q.poll() != null) {
break;
}
test = null; //it is important
System.gc();
lock.wait(100);//should not lock.wait()
}
}
System.out.println(1111111);
}
}
sb が言うように、ステートメント ( test=null) は key.GC が null を割り当てるテスト オブジェクトを収集します。