Пример использования PhantomReference
В ленте Twitter прочитал задачку про PhantomReference Я решил посмотреть, как используются фантомные ссылки в Одноклассниках. В приведенном коде я использую идею из кодовой базы проекта, но с добавлением собственных комментариев и багов, в силу скудоумия:
package ru.yamakarov.examples;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.util.concurrent.ConcurrentHashMap;
public class Phantom {
public static void main(String[] args) {
test();
System.gc();
}
private static void test() {
// Ресурс, который мы хотим почистить, когда объект станет доступен только по фантомной ссылке
String resource = "resource";
// Объект использующий ресурс
Garbage garbage = new Garbage(resource);
new Cleaner(garbage) {
@Override
void clean() {
System.out.println("Cleaned " + resource);
}
};
}
}
// Класс освобождающий ресурсы после того, как использующий их объект стал недоступен
abstract class Cleaner extends PhantomReference<Object> {
// Очередь в которую попадают объекты требующие очистки
private static ReferenceQueue<Object> queue = new ReferenceQueue<>();
// Храним ссылки, чтобы они не были собраны сборкой мусора
private static ConcurrentHashMap<Cleaner, Cleaner> allCleaners = new ConcurrentHashMap<>();
static {
Thread thread = new Thread(() -> {
while (true) {
try {
Cleaner ref = (Cleaner) queue.remove();
allCleaners.remove(ref);
ref.clean();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
// Делаем поток демоном, так как он должен остановиться когда закончилось приложение
thread.setDaemon(true);
thread.start();
}
public Cleaner(Object referent) {
super(referent, queue);
allCleaners.put(this, this);
}
abstract void clean();
}
class Garbage {
private final String resource;
public Garbage(String resource) {
this.resource = resource;
}
@Override
public String toString() {
return "Garbage{" +
"resource='" + resource + '\'' +
'}';
}
}