मैं उन तंत्रों को लागू करने की कोशिश कर रहा हूं जो कैश की गई फ़ाइलों को हटाते हैं, जब ऑब्जेक्ट्स उन्हें मरते हैं, और किसी ऑब्जेक्ट के कचरे के संग्रह पर अधिसूचित होने के लिए PhantomReference
का उपयोग करने का निर्णय लिया जाता है। समस्या यह है कि मैं ReferenceQueue
के अजीब व्यवहार का अनुभव करता रहता हूं। जब मैं अपने कोड में कुछ बदलता हूं तो अचानक यह वस्तुएं नहीं लाता है। बुला gc
कई बार आदिमेरी वस्तुएं क्यों मर जाएंगी?
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.
जरूरत नहीं कहने के लिए, sleep
समय बदल रहा है, तो मैं परीक्षण के लिए इस उदाहरण करने की कोशिश की, और एक ही समस्या में पड़ गए:
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();
}
}
}
उत्पादन होता है काम नहीं किया
अद्यतन
के रूप में सुझाव दिया है, मैं अपने संदर्भ है, जो समस्या हल की Reference.enqueue()
कहा जाता है।
अजीब बात यह है कि मेरे पास कुछ कोड है जो पूरी तरह से काम करता है (बस इसका परीक्षण करता है), हालांकि यह कभी भी enqueue
पर कॉल नहीं करता है। क्या यह संभव है कि Reference
को Map
में किसी भी तरह से जादुई रूप से संदर्भ को घेर लिया जाए?
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();
}
}
कुछ फ़िल्टर्ड उत्पादन:
2013-08-05 22: 35: फाइल करने के लिए 01,932 डीबग सहेजें छवि: <> \ AppData \ Local \ अस्थायी \ tmp7..0.PNG
2013-08-05 22: 35: 03,379 DEBUG अप्रयुक्त फ़ाइल को हटा रहा है: <> \ AppData \ Local \ Temp \ tmp7..0.PNG सोमवार को बनाया गया 05 अगस्त 22:35:02 आईडीटी 2013
आप वास्तव में कुछ भी नहीं लगाते हैं। –
तो मुझे 'enqueue()' कॉल करना चाहिए ... इसे मिला, धन्यवाद! – Elist
मेरा उत्तर, आखिरी पंक्ति देखें। –