การใช้การอ้างอิงที่อ่อนแอเป็นสิ่งที่ฉันไม่เคยเห็นมาก่อนในการนำมาใช้ดังนั้นฉันจึงพยายามหาว่ากรณีการใช้งานสำหรับพวกเขาคืออะไรและการนำไปใช้งานอย่างไร คุณจำเป็นต้องใช้ a WeakHashMap
หรือเมื่อใดWeakReference
และมีการนำมาใช้อย่างไร
การใช้การอ้างอิงที่อ่อนแอเป็นสิ่งที่ฉันไม่เคยเห็นมาก่อนในการนำมาใช้ดังนั้นฉันจึงพยายามหาว่ากรณีการใช้งานสำหรับพวกเขาคืออะไรและการนำไปใช้งานอย่างไร คุณจำเป็นต้องใช้ a WeakHashMap
หรือเมื่อใดWeakReference
และมีการนำมาใช้อย่างไร
คำตอบ:
ปัญหาหนึ่งที่มีการอ้างอิงที่ดีคือการแคชโดยเฉพาะกับโครงสร้างที่มีขนาดใหญ่มากเช่นรูปภาพ สมมติว่าคุณมีแอปพลิเคชันที่ต้องทำงานกับรูปภาพที่ผู้ใช้จัดหาเช่นเครื่องมือออกแบบเว็บไซต์ที่ฉันทำงาน โดยปกติคุณต้องการแคชอิมเมจเหล่านี้เนื่องจากการโหลดจากดิสก์มีราคาแพงมากและคุณต้องการหลีกเลี่ยงความเป็นไปได้ที่จะมีอิมเมจ (ขนาดมหึมา) สองชุดในหน่วยความจำทันที
เนื่องจากแคชรูปภาพควรป้องกันไม่ให้เราโหลดรูปภาพซ้ำเมื่อเราไม่ต้องการจริงๆคุณจะรู้ได้อย่างรวดเร็วว่าแคชควรมีการอ้างอิงถึงภาพใด ๆ ที่อยู่ในหน่วยความจำแล้ว แม้ว่าจะมีการอ้างอิงที่แข็งแกร่งทั่วไปการอ้างอิงนั้นจะบังคับให้ภาพยังคงอยู่ในหน่วยความจำซึ่งคุณจะต้องพิจารณาว่าเมื่อใดที่ภาพไม่จำเป็นในหน่วยความจำและลบออกจากแคชเพื่อให้มีสิทธิ์ในการรวบรวมขยะ คุณถูกบังคับให้ทำซ้ำการทำงานของตัวรวบรวมขยะและกำหนดด้วยตนเองว่าวัตถุควรอยู่ในหน่วยความจำหรือไม่
การทำความเข้าใจข้อมูลอ้างอิงที่อ่อนแออีธานนิโคลัส
WeakHashMap
ได้
WeakReference
กับ SoftReference
ความแตกต่างหนึ่งที่จะมีความชัดเจนเกี่ยวกับความแตกต่างระหว่างที่และWeakReference
SoftReference
โดยทั่วไป a WeakReference
จะเป็นGC-dโดยJVMอย่างกระตือรือร้นเมื่อวัตถุที่อ้างอิงไม่มีการอ้างอิงอย่างหนัก SoftReference
d วัตถุบนมืออื่น ๆ ที่จะมีแนวโน้มที่จะถูกทิ้งไว้เกี่ยวกับการเก็บขยะจนจริงๆต้องเรียกคืนหน่วยความจำ
แคชที่ค่าถูกเก็บไว้ภายในWeakReference
s จะไร้ประโยชน์สวย (ในWeakHashMap
มันเป็นกุญแจที่มีการอ้างอิงอ่อน) SoftReferences
มีประโยชน์ในการห่อค่าเมื่อคุณต้องการใช้แคชซึ่งสามารถขยายและย่อขนาดด้วยหน่วยความจำที่มีอยู่
หนึ่งการใช้งานทั่วไปของWeakReference
s และWeakHashMap
s โดยเฉพาะคือการเพิ่มคุณสมบัติให้กับวัตถุ ในบางครั้งคุณต้องการเพิ่มฟังก์ชันการทำงานหรือข้อมูลลงในวัตถุ แต่การทำคลาสย่อยและ / หรือการจัดองค์ประกอบนั้นไม่ใช่ตัวเลือกในกรณีนั้นสิ่งที่ชัดเจนที่ต้องทำคือการสร้าง hashmap ที่เชื่อมโยงวัตถุที่คุณต้องการขยายไปยังคุณสมบัติที่คุณต้องการเพิ่ม . เมื่อใดก็ตามที่คุณต้องการอสังหาริมทรัพย์คุณก็สามารถค้นหาได้ในแผนที่ อย่างไรก็ตามหากวัตถุที่คุณเพิ่มคุณสมบัติมีแนวโน้มที่จะถูกทำลายและสร้างขึ้นมากมายคุณสามารถจบลงด้วยวัตถุเก่า ๆ จำนวนมากในแผนที่ของคุณโดยใช้หน่วยความจำจำนวนมาก
หากคุณใช้WeakHashMap
วัตถุแทนจะออกจากแผนที่ของคุณทันทีที่ไม่ได้ใช้งานโดยส่วนที่เหลือของโปรแกรมซึ่งเป็นพฤติกรรมที่ต้องการ
ผมต้องทำเช่นนี้เพื่อเพิ่มข้อมูลบางอย่างเพื่อjava.awt.Component
ที่จะได้รอบการเปลี่ยนแปลงในระหว่าง JRE 1.4.2 และ 1.5 ฉันจะได้รับการแก้ไขได้โดย subclassing ส่วนประกอบผมเป็น int สนใจ (ทุกJButton
, JFrame
, JPanel
.... ) แต่ตอนนี้มาก ง่ายขึ้นด้วยรหัสน้อย
อีกกรณีที่มีประโยชน์สำหรับการWeakHashMap
และWeakReference
เป็นการดำเนินการรีจิสทรีฟัง
เมื่อคุณสร้างบางสิ่งที่ต้องการฟังเหตุการณ์บางอย่างโดยปกติคุณจะลงทะเบียนผู้ฟังเช่น
manager.registerListener(myListenerImpl);
หากmanager
ร้านค้าของคุณฟังด้วยWeakReference
นั่นหมายความว่าคุณไม่จำเป็นต้องลบการลงทะเบียนเช่นด้วยmanager.removeListener(myListenerImpl)
เพราะมันจะถูกลบโดยอัตโนมัติเมื่อผู้ฟังของคุณหรือส่วนประกอบของคุณที่ถือผู้ฟังไม่สามารถใช้งานได้
แน่นอนว่าคุณยังสามารถลบผู้ฟังออกได้ด้วยตนเองแต่ถ้าคุณไม่ทำหรือลืมมันก็จะไม่ทำให้หน่วยความจำรั่วและจะไม่ป้องกันผู้ฟังที่คุณเก็บขยะ
ในกรณีที่ไม่WeakHashMap
เข้ามาในภาพหรือไม่
รีจิสตรีผู้ฟังที่ต้องการจัดเก็บ listeners ที่รีจิสเตอร์เนื่องจากWeakReference
ต้องการคอลเล็กชันเพื่อเก็บการอ้างอิงเหล่านี้ ไม่มีWeakHashSet
การนำไปใช้ในไลบรารี Java มาตรฐานเพียงอย่างเดียวWeakHashMap
แต่เราสามารถใช้อันหลังเพื่อ "ใช้" ฟังก์ชั่นของอันแรก:
Set<ListenerType> listenerSet =
Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());
ด้วยสิ่งนี้listenerSet
เพื่อลงทะเบียนผู้ฟังใหม่คุณเพียงแค่เพิ่มมันเข้าไปในชุดและแม้ว่ามันจะไม่ถูกลบออกอย่างชัดเจนหากผู้ฟังไม่ได้ถูกอ้างอิงอีกต่อไป JVM จะถูกลบโดยอัตโนมัติ
WeakHashMap
เมื่อใดก็ตามที่คุณต้องการHashMap
วัตถุ ดังนั้นคุณจะไม่ต้องทำhashmap.remove ด้วยตนเองเลยเพราะรายการจะถูกลบออกโดยอัตโนมัติเมื่อ obj อยู่นอกขอบเขต! มายากลอย่างแท้จริง! ดังกล่าวสับมายากลที่น่าเกลียดเป็นfacepalm สมบูรณ์
WeakReference
ช่วยลดความยุ่งยากอย่างมากฐานรหัสและหลีกเลี่ยงข้อบกพร่องที่ไม่จำเป็นที่เกี่ยวข้องกับการล้มเหลวในการยกเลิกการสมัคร ข้อเสียคืออะไร
บล็อกโพสต์นี้แสดงให้เห็นถึงการใช้หลักสูตรทั้ง: Java: ตรงกันเกี่ยวกับประชาชน การใช้งานมีลักษณะดังนี้:
private static IdMutexProvider MUTEX_PROVIDER = new IdMutexProvider();
public void performTask(String resourceId) {
IdMutexProvider.Mutex mutext = MUTEX_PROVIDER.getMutex(resourceId);
synchronized (mutext) {
// look up the resource and do something with it
}
}
IdMutextProvider จัดเตรียมวัตถุที่เป็น id เพื่อซิงโครไนซ์ ข้อกำหนดคือ:
นี่คือความสำเร็จโดยใช้แผนที่จัดเก็บข้อมูลภายในประเภท:
WeakHashMap<Mutex, WeakReference<Mutex>>
วัตถุมีทั้งคีย์และค่า เมื่อไม่มีสิ่งใดที่อยู่นอกแผนที่มีการอ้างอิงถึงวัตถุอย่างหนักอาจเป็นการรวบรวมขยะ ค่าในแผนที่จะถูกเก็บไว้ด้วยการอ้างอิงอย่างหนักดังนั้นค่าจะต้องห่อในWeakReferenceเพื่อป้องกันการรั่วไหลของหน่วยความจำ จุดสุดท้ายนี้ได้รับการคุ้มครองในJavadoc
หากคุณต้องการติดตามวัตถุทั้งหมดที่สร้างขึ้นในระดับหนึ่ง เพื่อให้วัตถุเหล่านี้ยังคงถูกเก็บขยะคุณยังคงมีรายการ / แผนที่ของการอ้างอิงที่อ่อนแอไปยังวัตถุแทนที่จะเป็นวัตถุเอง
ตอนนี้ถ้าใครบางคนสามารถอธิบายการอ้างอิงผีกับฉันฉันจะมีความสุข ...
ตามที่ระบุไว้ข้างต้นการอ้างอิงที่อ่อนแอจะถูกเก็บไว้ตราบเท่าที่มีการอ้างอิงที่แข็งแกร่งอยู่
ตัวอย่างการใช้งานคือการใช้ WeakReference ภายใน Listeners ดังนั้น Listeners จะไม่ทำงานอีกต่อไปเมื่อการอ้างอิงหลักไปยังวัตถุเป้าหมายหายไป โปรดทราบว่านี่ไม่ได้หมายความว่า WeakReference จะถูกลบออกจากรายการผู้ฟังจำเป็นต้องล้างข้อมูล แต่สามารถดำเนินการได้ตามเวลาที่กำหนด สิ่งนี้ยังมีผลในการป้องกันไม่ให้วัตถุฟังการอ้างอิงที่รัดกุมและในที่สุดก็เป็นแหล่งของหน่วยความจำที่ขยายตัว ตัวอย่าง: คอมโพเนนต์ Swing Swing ที่อ้างถึงโมเดลที่มีวงจรชีวิตยาวนานกว่าหน้าต่าง
ในขณะที่เล่นกับผู้ฟังตามที่อธิบายไว้ข้างต้นเราตระหนักได้อย่างรวดเร็วว่าวัตถุได้รับการรวบรวม "ทันที" จากมุมมองของผู้ใช้
หนึ่งในโลกแห่งความเป็นจริงที่ฉันใช้สำหรับ WeakReferences คือถ้าคุณมีวัตถุชิ้นเดียวที่มีขนาดใหญ่มากซึ่งไม่ค่อยได้ใช้ คุณไม่ต้องการเก็บไว้ในหน่วยความจำเมื่อไม่จำเป็น แต่ถ้าเธรดอื่นต้องการวัตถุเดียวกันคุณไม่ต้องการเธรดทั้งสองในหน่วยความจำ คุณสามารถเก็บการอ้างอิงที่อ่อนแอไปยังวัตถุบางแห่งและการอ้างอิงที่ยากในวิธีการที่ใช้ เมื่อวิธีการทั้งสองเสร็จสิ้นวัตถุจะถูกเก็บรวบรวม
ฉันค้นหา google code เพื่อ "new WeakHashMap ()"
ฉันได้คู่ที่ตรงกันจากโครงการ classpath ของ GNU และ
คุณสามารถใช้ weakhashmap เพื่อใช้การแคชที่ไม่มีทรัพยากรสำหรับการสร้างวัตถุที่กว้างขวาง
แต่โปรดทราบว่าไม่ต้องการมีวัตถุที่ไม่แน่นอน ฉันใช้เพื่อแคชผลลัพธ์แบบสอบถาม (ซึ่งใช้เวลาประมาณ 400 ms ในการดำเนินการ) กับเครื่องมือค้นหาข้อความซึ่งไม่ค่อยได้รับการปรับปรุง