В ленте 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 + '\'' +
'}' ;
}
}