Önbelleğe alınmış nesneleri silerken, onları öldüren nesneler silindiğinde ve bir nesnenin çöp toplamasında bildirim almak için PhantomReference
s kullanmaya karar veren bir mekanizmayı uygulamaya çalışıyorum. Sorun şu ki, ReferenceQueue
'un tuhaf davranışlarını devam ettirmekteyim. Kodumda bir şeyi değiştirdiğimde, artık nesneleri bir anda almaz. gc
birden çok kez vb çağırarak,Nesnelerim neden ölmüyor?
I'm born.
I'm born.
I'm born.
I'm born.
I'm born.
I'm born.
I'm born.
I'm born.
I'm born.
I'm born.
Söylemeye gerek sleep
zaman değişen: Ben test için bu örneği yapmaya çalıştı ve aynı sorun koştu:
public class DeathNotificationObject {
private static ReferenceQueue<DeathNotificationObject>
refQueue = new ReferenceQueue<DeathNotificationObject>();
static {
Thread deathThread = new Thread("Death notification") {
@Override
public void run() {
try {
while (true) {
refQueue.remove();
System.out.println("I'm dying!");
}
} catch (Throwable t) {
t.printStackTrace();
}
}
};
deathThread.setDaemon(true);
deathThread.start();
}
public DeathNotificationObject() {
System.out.println("I'm born.");
new PhantomReference<DeathNotificationObject>(this, refQueue);
}
public static void main(String[] args) {
for (int i = 0 ; i < 10 ; i++) {
new DeathNotificationObject();
}
try {
System.gc();
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
çıkışı işe yaramadı önerildiği gibi
GÜNCELLEME
ben de sorunu çözüldü benim referans ait Reference.enqueue()
aradı.
Garip olan şey, hiçbir zaman mükemmel çalışıyor (sadece test ettim), hiç bir zaman enqueue
numaralı telefonu aramamasına rağmen. Reference
'un bir Map
içine yerleştirilmesi, bir şekilde referansı sihirli bir şekilde sıralamak mümkün mü?
public class ElementCachedImage {
private static Map<PhantomReference<ElementCachedImage>, File>
refMap = new HashMap<PhantomReference<ElementCachedImage>, File>();
private static ReferenceQueue<ElementCachedImage>
refQue = new ReferenceQueue<ElementCachedImage>();
static {
Thread cleanUpThread = new Thread("Image Temporary Files cleanup") {
@Override
public void run() {
try {
while (true) {
Reference<? extends ElementCachedImage> phanRef =
refQue.remove();
File f = refMap.remove(phanRef);
Calendar c = Calendar.getInstance();
c.setTimeInMillis(f.lastModified());
_log.debug("Deleting unused file: " + f + " created at " + c.getTime());
f.delete();
}
} catch (Throwable t) {
_log.error(t);
}
}
};
cleanUpThread.setDaemon(true);
cleanUpThread.start();
}
ImageWrapper img = null;
private static Logger _log = Logger.getLogger(ElementCachedImage.class);
public boolean copyToFile(File dest) {
try {
FileUtils.copyFile(img.getFile(), dest);
} catch (IOException e) {
_log.error(e);
return false;
}
return true;
}
public ElementCachedImage(BufferedImage bi) {
if (bi == null) throw new NullPointerException();
img = new ImageWrapper(bi);
PhantomReference<ElementCachedImage> pref =
new PhantomReference<ElementCachedImage>(this, refQue);
refMap.put(pref, img.getFile());
new Thread("Save image to file") {
@Override
public void run() {
synchronized(ElementCachedImage.this) {
if (img != null) {
img.saveToFile();
img.getFile().deleteOnExit();
}
}
}
}.start();
}
}
Bazı süzülmüş çıkışı:
2013/08/05 22: 35: 01.932 DEBUG Resmi kaydet dosyaya: <> \ AppData \ Local \ Temp tmp7..0.PNG
\2013-08-05 22: 35: 03,379 DEBUG Kullanılmayan dosyayı silme: <> \ AppData \ Local \ Temp \ tmp7..0.PNG, 09.09.2012 tarihinde saat 22: 35'te alındı. IDT 2013
Aslında hiçbir şeyi düzenlemezsiniz. –
Bu yüzden 'enqueue() 'yi çağırmalıyım ... anladım, teşekkürler! – Elist
Cevabım, son satırımı görün. –