ตัวอย่างเช่นแคชเครือข่ายกำลังโหลดรูปภาพ:
// รับหน่วยความจำสูงสุดที่จัดสรรโดยแอปพลิเคชัน int maxMemory = (int) runtime.getRuntime (). maxMemory (); // รับ 1/5 ของหน่วยความจำที่จะใช้เมื่อขนาดแคชเป็น int cachesize = maxMemory/5; // LRUCACHE LRUCACHE ทันที = ใหม่ lrucache <String, bitmap> (cachsize) {// วิธีการภายในขนาดของขนาดแคชของแต่ละภาพป้องกันขนาด int ของ (คีย์สตริง, ค่าบิตแมป) {// เรียกว่าทุกครั้งที่แคชถูกเก็บไว้ value.getByTecount (); }}; รหัสข้างต้นมักจะอยู่ในวิธีการเริ่มต้น
ในความเป็นจริงคลาส Lurcache สามารถเข้าใจได้ว่าเป็นแผนที่คลาสแผนที่ มีวิธีการใส่และรับ
ถัดไปการโทรและรับวิธีการเข้าถึงทรัพยากรที่แคช
การเพิ่มของ Lurcache:
โมฆะสาธารณะ PutbitMaptocache (url สตริง, บิตแมปบิตแมป) {ถ้า (getBitMapFromCache (url) == null) {// ตัดสินว่าแคชปัจจุบันมีอยู่ lrucache.put (url, บิตแมป); }} lurcache get: บิตแมปสาธารณะ getBitMap FromCache (url string) {return lrucache.get (url); // lrucache สามารถถือได้ว่าเป็นแผนที่} การเรียกวิธีการเพิ่มและรับข้างต้นสามารถแคชทรัพยากรซึ่งค่อนข้างง่าย
แต่ระวังว่า LruCache lruCache=new LruCache<String, Bitmap>(cachSize) สามารถใหม่ได้เพียงครั้งเดียวมิฉะนั้นวัตถุที่แตกต่างกันจะถูกแคชแตกต่างกัน
ติดกับคลาส lrucache ของ Android
แพ็คเกจ Android.util; นำเข้า java.util.linkedhashmap; นำเข้า java.util.map; /*** แคชที่มีการอ้างอิงที่แข็งแกร่งถึงจำนวนที่ จำกัด ทุกครั้งที่มีการเข้าถึงค่า * จะถูกย้ายไปที่หัวของคิว เมื่อค่าถูกเพิ่มลงในแคชเต็มค่าที่ท้ายของคิวนั้นจะถูกขับไล่และอาจ * มีสิทธิ์ได้รับการรวบรวมขยะ * แคชบันทึกการอ้างอิงที่แข็งแกร่งเพื่อ จำกัด จำนวนเนื้อหา เมื่อใดก็ตามที่มีการเข้าถึงรายการรายการจะย้ายไปที่หัวของคิว * เมื่อมีการเพิ่มรายการใหม่เมื่อแคชเต็มรูปแบบรายการที่ส่วนท้ายของคิวจะถูกรีไซเคิล * <p> หากค่าที่แคชของคุณถือทรัพยากรที่จำเป็นต้องเปิดตัวอย่างชัดเจน * แทนที่ {@link #EntryRemoved} * หากควรคำนวณแคชตามความต้องการสำหรับคีย์ที่เกี่ยวข้อง * แทนที่ {@link #Create} สิ่งนี้ทำให้รหัสการโทรง่ายขึ้นทำให้สามารถส่งคืนค่าได้เสมอแม้ว่าจะมีแคชพลาดก็ตาม * หากรายการที่สอดคล้องกับคีย์หายไปให้เขียนใหม่ให้สร้าง () สิ่งนี้ทำให้รหัสการโทรง่ายขึ้นและจะกลับมาเสมอแม้ว่ามันจะหายไป * <p> โดยค่าเริ่มต้นขนาดแคชจะถูกวัดในจำนวนรายการ แทนที่ * {@link #sizeof} เพื่อปรับขนาดแคชในหน่วยต่าง ๆ ตัวอย่างเช่นแคชนี้ * จำกัด บิตแมป 4MIB: ขนาดแคชเริ่มต้นคือจำนวนรายการที่วัดได้และขนาดของแคชถูกแทนที่เพื่อคำนวณขนาด * ของรายการที่แตกต่างกัน * <pre> {@code * int cachesize = 4 * 1024 * 1024; // 4mib * lrucache <string, bitmap> bitmapcache = ใหม่ lrucache <สตริง, bitmap> (cachesize) { * การป้องกัน int sizeof (คีย์สตริง, ค่าบิตแมป) { * return value.getByTeCount (); *} *}} </pre> * * * <p> คลาสนี้เป็นเธรดที่ปลอดภัย ดำเนินการหลายตัวแคชแบบอะตอมโดยการซิงโครไนซ์บนแคช: <pre> {@code * ซิงโครไนซ์ (แคช) { * ถ้า (cache.get (คีย์) == null) { * cache.put (คีย์, ค่า); *} *}} </pre> * * * <p> คลาสนี้ไม่อนุญาตให้ใช้ null เป็นคีย์หรือค่า ค่าส่งคืน * ของ null จาก {@link #get}, {@link #put} หรือ {@link #Remove} คือ * ไม่น่าสังเกต: คีย์ไม่ได้อยู่ในแคช * คีย์หรือค่าคือ null * เมื่อ get (), put (), ลบ () ค่าส่งคืนเป็นโมฆะรายการที่สอดคล้องกันของคีย์ไม่ได้อยู่ในแคช */ คลาสสาธารณะ lrucache <k, v> {ส่วนตัวสุดท้าย linkedhashmap <k, v> แผนที่; /** ขนาดของแคชนี้ในหน่วย ไม่จำเป็นต้องมีจำนวนองค์ประกอบ */ ขนาด int ส่วนตัว; // ขนาดที่จัดเก็บ maxsize ส่วนตัว // พื้นที่เก็บข้อมูลสูงสุดที่ระบุไว้เป็นส่วนตัว int putcount; // จำนวนของ put private int createCount; // จำนวนครั้งที่สร้างการขับไล่ int ส่วนตัว; // จำนวนครั้งของการรีไซเคิลภายใน int int int hitcount; // จำนวนของฮิตส่วนตัว int misscount; // จำนวนของ Lost/** * @param maxsize สำหรับแคชที่ไม่ได้แทนที่ {@link #sizeof} นี่คือ * จำนวนสูงสุดของรายการในแคช สำหรับแคชอื่น ๆ ทั้งหมด * นี่คือผลรวมสูงสุดของขนาดของรายการในแคชนี้ */ lrucache สาธารณะ (int maxsize) {ถ้า (maxsize <= 0) {โยน unlegalargumentException ใหม่ ("maxSize <= 0"); } this.maxSize = maxSize; this.map = ใหม่ linkedHashMap <k, v> (0, 0.75f, true); } /** * ส่งคืนค่าสำหรับ {@code key} หากมีอยู่ในแคชหรือสามารถ * สร้างโดย {@code #Create} หากค่าถูกส่งคืนมันจะถูกย้ายไปที่หัว * ของคิว สิ่งนี้จะส่งคืนค่า null หากค่าไม่ได้ถูกแคชและไม่สามารถสร้างได้ ส่งคืนรายการที่เกี่ยวข้องด้วยคีย์หรือสร้างรายการส่งคืนรายการที่เกี่ยวข้อง รายการที่เกี่ยวข้องจะย้ายไปที่หัวของคิว * หากค่าของรายการไม่ได้ถูกแคชหรือไม่สามารถสร้างได้ให้ส่งคืนค่า null */ สาธารณะสุดท้าย v รับ (k key) {if (key == null) {โยน nullpointerexception ใหม่ ("key == null"); } v MapValue; ซิงโครไนซ์ (นี่) {mapValue = map.get (คีย์); if (mapValue! = null) {hitCount ++; // hit return mapvalue; } missCount ++; // lost} / * * พยายามสร้างค่า สิ่งนี้อาจใช้เวลานานและแผนที่ * อาจแตกต่างกันเมื่อสร้าง () ส่งคืน หากค่าที่ขัดแย้งกันถูกเพิ่ม * ลงในแผนที่ในขณะที่สร้าง () ทำงานอยู่เราจะทิ้งค่านั้นไว้ใน * แผนที่และปล่อยค่าที่สร้างขึ้น * หากหายไปให้ลองสร้างรายการ */ v createDvalue = สร้าง (คีย์); if (createDvalue == null) {return null; } ซิงโครไนซ์ (นี่) {createCount ++; // สร้าง ++ mapValue = map.put (คีย์, createdValue); if (mapValue! = null) {// มีความขัดแย้งดังนั้นให้เลิกทำแล้วใส่ตัวครั้งสุดท้าย // หากมี oldValue ก่อนหน้านั้น undo put () map.put (key, mapValue); } else {size += safesizeof (คีย์, createDvalue); }} if (mapValue! = null) {entryRemoved (false, key, createdValue, mapValue); กลับ MapValue; } else {trimtosize (maxsize); กลับมาสร้างค่า; }} /*** แคช {@code value} สำหรับ {@code key} ค่าถูกย้ายไปที่หัวของ * คิว * * @return ค่าก่อนหน้านี้แมปโดย {@code key} */ สาธารณะสุดท้าย V Put (k key, v value) {if (key == null || value == null) {โยน nullpointerexception ใหม่ ("key == null || value == null"); } v ก่อนหน้า; ซิงโครไนซ์ (นี่) {putcount ++; ขนาด += safesizeof (คีย์, ค่า); previous = map.put (คีย์, ค่า); ถ้า (ก่อนหน้า! = null) {// ค่าที่ส่งคืนก่อนหน้านี้คือขนาด -= safeSizeOf (คีย์, ก่อนหน้า); }} ถ้า (ก่อนหน้า! = null) {entryRemoved (เท็จ, คีย์, ก่อนหน้า, ค่า); } trimtosize (maxsize); กลับมาก่อน; } /*** @param maxsize ขนาดสูงสุดของแคชก่อนที่จะกลับมา อาจเป็น -1 * เพื่อขับไล่องค์ประกอบขนาด 0 * ล้างพื้นที่แคช*/ โมฆะส่วนตัว trimtosize (int maxsize) {ในขณะที่ (จริง) {k key; ค่า V; ซิงโครไนซ์ (นี่) {ถ้า (ขนาด <0 || (map.isEmpty () && size! = 0)) {โยนใหม่ผิดกฎหมาย EllegalStateException (getClass (). getName () + ".sizeof () คือการรายงานผลลัพธ์ที่ไม่สอดคล้องกัน!"); } if (size <= maxSize) {break; } map.entry <k, v> toEvict = map.eldest (); if (toEvict == null) {break; } key = toEvict.getKey (); value = toEvict.getValue (); MAP.REMOVE (กุญแจ); ขนาด -= safesizeof (คีย์, ค่า); EvictionCount ++; } entryRemoved (true, key, value, null); }} /*** ลบรายการสำหรับ {@code key} หากมีอยู่ * ลบรายการแคชที่สอดคล้องกันของคีย์และส่งคืนค่าที่สอดคล้องกัน * @return ค่าก่อนหน้านี้แมปโดย {@code key} */ สาธารณะสุดท้าย v ลบ (k key) {if (key == null) {โยน nullpointerexception ใหม่ ("key == null"); } v ก่อนหน้า; ซิงโครไนซ์ (นี่) {previous = map.remove (คีย์); ถ้า (ก่อนหน้า! = null) {size -= safeSizeOf (คีย์, ก่อนหน้า); }} ถ้า (ก่อนหน้า! = null) {entryRemoved (เท็จ, คีย์, ก่อนหน้า, null); } return ก่อนหน้า; } /*** เรียกร้องให้มีรายการที่ถูกขับไล่หรือลบออก วิธีนี้คือ * เรียกใช้เมื่อค่าถูกขับไล่เพื่อให้มีพื้นที่ว่างโดยการโทรไปที่ * {@link #Remove} หรือแทนที่ด้วยการโทรไปที่ {@link #put} การใช้งานเริ่มต้น * ไม่ได้ทำอะไรเลย * เรียกเมื่อรายการรีไซเคิลหรือลบ เปลี่ยนวิธีการเมื่อค่ารีไซเคิลและปลดปล่อยพื้นที่เก็บข้อมูลจะเรียกว่าลบหรือเมื่อเปลี่ยนค่ารายการการใช้งานเริ่มต้นจะไม่ทำอะไรเลย * <p> วิธีการที่เรียกโดยไม่ต้องซิงโครไนซ์: เธรดอื่น ๆ อาจ * เข้าถึงแคชในขณะที่วิธีนี้กำลังดำเนินการ * * @param ขับไล่จริงถ้ารายการถูกลบออกเพื่อให้มีพื้นที่, เท็จ * หากการลบเกิดจาก {@link #put} หรือ {@link #Remove} * จริง --- ใส่หรือลบสาเหตุ * @param newValue ค่าใหม่สำหรับ {@code key} หากมีอยู่ หากไม่ใช่ NULL * การลบนี้เกิดจาก {@link #put} มิฉะนั้นมันเกิดจาก * การขับไล่หรือ {@link #remove} * / Void Void entryRemoved (Boolean Evicted, K Key, V oldValue, v newValue) {} / *** เรียกว่าหลังจากแคชพลาดเพื่อคำนวณค่าสำหรับคีย์ที่สอดคล้องกัน * ส่งคืนค่าที่คำนวณหรือเป็นโมฆะหากไม่สามารถคำนวณค่าได้ * การใช้งานเริ่มต้นจะส่งคืนค่า NULL * เมื่อรายการหายไปมันจะถูกเรียกให้ส่งคืนค่าที่สอดคล้องกันที่คำนวณได้หรือ null * <p> วิธีการที่เรียกโดยไม่ต้องซิงโครไนซ์: เธรดอื่น ๆ อาจ * เข้าถึงแคชในขณะที่วิธีนี้กำลังดำเนินการ * * <p> หากค่าสำหรับ {@code key} มีอยู่ในแคชเมื่อวิธีนี้ * ส่งคืนค่าที่สร้างขึ้นจะถูกปล่อยด้วย {@link #EntryRemoved} * และเปิดเผย สิ่งนี้สามารถเกิดขึ้นได้เมื่อหลายเธรดร้องขอคีย์เดียวกัน * ในเวลาเดียวกัน (ทำให้หลายค่าที่จะสร้าง) หรือเมื่อมีการเรียกเธรด * หนึ่ง {@link #put} ในขณะที่อีกค่ากำลังสร้างค่าสำหรับคีย์ * เดียวกัน */ ป้องกัน v สร้าง (k key) {return null; } ส่วนตัว int safesizeof (k คีย์, ค่า V) {int result = sizeof (คีย์, ค่า); if (ผลลัพธ์ <0) {โยน unglegalStateException ใหม่ ("ขนาดลบ:" + คีย์ + "=" + ค่า); } ผลตอบแทนผลลัพธ์; } /** * ส่งคืนขนาดของรายการสำหรับ {@code key} และ {@code value} ในหน่วยที่กำหนดโดยผู้ใช้ การใช้งานเริ่มต้นจะส่งคืน 1 เพื่อให้ขนาด * คือจำนวนรายการและขนาดสูงสุดคือจำนวนสูงสุดของรายการ * ส่งคืนขนาดของรายการที่ผู้ใช้กำหนดค่าเริ่มต้น 1 แสดงถึงจำนวนรายการขนาดสูงสุดคือค่ารายการสูงสุด* <p> ขนาดของรายการจะต้องไม่เปลี่ยนแปลงในขณะที่อยู่ในแคช */ การป้องกัน int sizeof (k คีย์, ค่า V) {return 1; } /*** ล้างแคชการเรียก {@link #EntryRemoved} ในแต่ละรายการที่ถูกลบ * Clear Cache */ Public Final Void Evictall () {trimtosize (-1); // -1 จะขับไล่องค์ประกอบขนาด 0} /** * สำหรับแคชที่ไม่ได้แทนที่ {@link #sizeof} สิ่งนี้จะส่งคืนหมายเลข * ของรายการในแคช สำหรับแคชอื่น ๆ ทั้งหมดนี้จะส่งคืนผลรวมของขนาดของรายการในแคชนี้ */ สาธารณะที่ซิงโครไนซ์ขนาดสุดท้าย () {ขนาดคืน; } /** * สำหรับแคชที่ไม่ได้แทนที่ {@link #sizeof} สิ่งนี้จะส่งคืนจำนวนสูงสุด * ของรายการในแคช สำหรับแคชอื่น ๆ ทั้งหมดนี้จะส่งคืนผลรวมสูงสุดของขนาดของรายการในแคชนี้ */ สาธารณะที่ซิงโครไนซ์สุดท้าย int maxsize () {return maxsize; } /** * ส่งคืนจำนวนครั้ง {@link #get} ส่งคืนค่าที่มีอยู่แล้วในแคชแล้ว */ สาธารณะที่ซิงโครไนซ์สุดท้าย int hitcount () {return hitcount; } /** * ส่งคืนจำนวนครั้ง {@link #get} ส่งคืน null หรือจำเป็นต้องสร้างค่า * ใหม่ที่จะสร้าง */ สาธารณะที่ซิงโครไนซ์สุดท้าย int misscount () {return misscount; } /*** ส่งคืนจำนวนครั้ง {@link #Create (วัตถุ)} ส่งคืนค่า */ สาธารณะที่ซิงโครไนซ์สุดท้าย int createCount () {return createCount; } /*** ส่งคืนจำนวนครั้ง {@link #put} ถูกเรียก */ สาธารณะที่ซิงโครไนซ์สุดท้าย int putcount () {return putcount; } /*** ส่งคืนจำนวนค่าที่ถูกขับไล่ */ สาธารณะที่ซิงโครไนซ์สุดท้าย Int EvictionCount () {return EvictionCount; } /** * ส่งคืนสำเนาเนื้อหาปัจจุบันของแคชที่สั่งซื้อจากอย่างน้อย * เมื่อเร็ว ๆ นี้เข้าถึงได้เมื่อเร็ว ๆ นี้ ส่งคืนสำเนาของแคชปัจจุบันจากการเข้าถึงอย่างน้อยเมื่อเร็ว ๆ นี้ไปจนถึงการเข้าถึงล่าสุด แผนที่สุดท้ายที่ซิงโครไนซ์สาธารณะ <k, v> snapshot () {ส่งคืนใหม่ LinkedHashMap <k, v> (แผนที่); } @Override สาธารณะที่ซิงโครไนซ์สตริงสุดท้าย toString () {int accesses = hitCount + missCount; int hitpercent = เข้าถึง! = 0? (100 * HitCount / Accesses): 0; return string.format ("lrucache [maxsize =%d, hit =%d, misses =%d, hitrate =%d %%]", maxsize, hitcount, misscount, hitpercent); -