– Szia Amigo!
– Szia Rishi!
– Nos, milyen napod volt?
"Zseniális! Ma Bilaabo a rekurzióról, Ellie pedig a gyenge és lágy utalásokról mesélt."
– Mesélt önnek a fantomreferenciákról?
– A PhantomReference-ről beszél? Említette, de nem magyarázta el részletesen.
– Remek, akkor remélem, nem bánja, ha kitöltöm ezt a hiányt.
"Természetesen! Örömmel hallgatlak, Rishi!"
– Remek. Akkor kezdem.
"A fantomhivatkozások a leggyengébb hivatkozások az összes közül. Csak akkor érvényesülnek, ha egy objektumnak a fantomhivatkozásokon kívül más hivatkozása sincs."
"A PhantomReference egy összetett objektumtörlési eljárásban használatos. Erre akkor lehet szükség, ha egy objektum a Java gépen kívül csinál valamit, pl. alacsony szintű operációs rendszer függvényeket hív meg, állapotát fájlba írja, vagy valami más nagyon fontos dolgot csinál."
"Íme egy példa arra, hogyan használhatja:"
// Special queue for phantom objects
ReferenceQueue<Integer> queue = new ReferenceQueue<Integer>();
// List of phantom references
ArrayList<PhantomReference<Integer>> list = new ArrayList<PhantomReference<Integer>>();
// Create 10 objects and add them to the list using phantom references
for ( int i = 0; i < 10; i++)
{
Integer x = new Integer(i);
list.add(new PhantomReference<Integer>(x, queue));
}
"Újra az utolsó sorra szeretném felhívni a figyelmet. Nem csak az x objektum kerül át a PhantomReference- be , hanem egy speciális fantomhivatkozási sor is."
– Miért van szükségünk erre a sorra?
– Most ezt fogom elmondani.
"Ha elpusztítasz egy fantomreferencia által tartott tárgyat, az megsemmisül, de nem törlődik a memóriából! Mit gondolsz erről?!"
– Szóval, ez hogyan működik?
– Van itt jó néhány árnyalat, úgyhogy a legegyszerűbbel kezdem.
"Ha csak fantomhivatkozások maradnak egy objektumra, akkor ez történik vele:
" 1. lépés . A következő szemétgyűjtés során a finalize() metódus meghívásra kerül az objektumon. Ha azonban a finalize() metódus nem lett felülírva, akkor ez a lépés kimarad, és a 2. lépés azonnal végrehajtásra kerül."
" 2. lépés . A következő szemétgyűjtés során az objektum a fantomobjektumok speciális sorába kerül. A PhantomReference-ben a clear() metódus meghívásakor törlődik ebből a sorból."
"Ki hívja? Az objektumot törölték, igaz?"
"Nos, az objektum valóban meghalt a mi világunkban (a Java világban), de nem tűnt el. Fantomként marad – a fantomobjektumok sora még mindig tartalmaz utalást rá. Ugyanaz a ReferenceQueue, amelyre olyan gondosan hivatkozunk átadta a PhantomReference konstruktornak."
– Szóval ez a ReferenceQueue olyan, mint a túlvilág?
– Inkább egy fantomvilág.
"És egy fantomobjektumot csak úgy lehet törölni, ha a fantomreferenciáján a clear()-t meghívjuk."
"Íme, hogyan folytassuk az előző példát:"
// Special queue for phantom objects
ReferenceQueue<Integer> queue = new ReferenceQueue<Integer>();
// List of phantom references
ArrayList<PhantomReference<Integer>> list = new ArrayList<PhantomReference<Integer>>();
// Create 10 objects and add them to the list using phantom references
for ( int i = 0; i < 10; i++)
{
Integer x = new Integer(i);
list.add(new PhantomReference<Integer>(x, queue));
}
// Call the garbage collector and hope it will listen to us :)
// It should destroy all phantom reachable objects and put them in the queue
// of phantoms
System.gc();
// Get all objects from the queue
Reference<? extends Integer>referenceFromQueue;
while ((referenceFromQueue = queue.poll()) != null)
{
// Display the object on the screen
System.out.println(referenceFromQueue.get());
// Clear the reference
referenceFromQueue.clear();
}
"Megértem, hogy itt valami történik. Szinte még azt is pontosan értem, hogy mi történik."
– De hogyan használja ezt a gyakorlatban?
"Íme egy jobb példa:"
// Special queue for phantom objects
ReferenceQueue<Integer> queue = new ReferenceQueue<Integer>();
// List of phantom references
ArrayList<PhantomInteger> list = new ArrayList<PhantomInteger>();
// Create 10 objects and add them to the list using phantom references
for ( int i = 0; i < 10; i++)
{
Integer x = new Integer(i);
list.add(new PhantomInteger (x, queue));
}
Thread referenceThread = new Thread()
{
public void run()
{
while (true)
{
try
{
// Get the new object from the queue. If there is no object, then we wait!
PhantomInteger ref = (PhantomInteger)queue.remove();
// Call the close method on it
ref.close();
ref.clear();
}
catch (Exception ex)
{
// Write errors to a log
}
}
}
};
// Run the thread as a daemon
referenceThread.setDaemon(true);
referenceThread.start();
static class PhantomInteger extends PhantomReference<Integer>
{
PhantomInteger(Integer referent, ReferenceQueue<? super Integer> queue)
{
super(referent, queue);
}
private void close()
{
System.out.println("Bad Integer totally destroyed!");
}
}
– Három dolgot csináltunk itt.
"Először is létrehoztuk a PhantomInteger osztályt, amely örökli a PhantomReference < Integer > értéket."
"Másodszor, ennek az osztálynak van egy speciális bezárási () metódusa. Ennek a metódusnak az igénye indította el az egészet.
"Harmadszor deklaráltunk egy speciális szálat: referenceThread . Egy ciklusban vár, amíg egy másik objektum megjelenik a fantomsorban. Amint ez megtörténik, a szál eltávolítja az objektumot a fantomsorból, és meghívja a close () metódusát . a clear() módszer. És ennyi. A fantom továbbléphet egy jobb világ felé. A miénkben többé nem fog zavarni minket."
– Annyira érdekes, de minden sikerült.
"Tulajdonképpen egy sor haldokló objektumot követünk nyomon, és akkor mindegyikhez hívhatunk egy speciális metódust."
"De ne feledje, magán az objektumon nem hívhatja meg a metódust. Nem kaphat hivatkozást rá! A PhantomReference get() metódusa mindig nullát ad vissza. "
– De mi örököljük a PhantomReference-t!
"A get() metódus még a PhantomReference alosztályán belül is nullát ad vissza."
"Tehát csak elmentek egy hivatkozást az objektumra a konstruktorban"
"Ah. De egy ilyen hivatkozás StrongReference lenne, és az objektum soha nem kerül a fantomsorba!"
Oké, add fel. Ha ez lehetetlen, akkor lehetetlen.
"Rendben, jó. Remélem, tanultál valami értékeset a mai leckéből."
"Igen, annyi új anyag volt. És azt hittem, már mindent tudok. Köszönöm a leckét, Rishi."
"Szívesen. Ez az, menj pihenni. De ne felejtsd el, ma este van még egy leckénk."
GO TO FULL VERSION