<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理
    update1:第二個實現(xiàn),讀操作不必要采用獨占鎖,緩存顯然是讀多于寫,讀的時候一開始用獨占鎖是考慮到要遞增計數(shù)和更新時間戳要加鎖,不過這兩個變量都是采用原子變量,因此也不必采用獨占鎖,修改為讀寫鎖。
    update2:一個錯誤,老是寫錯關(guān)鍵字啊,LRUCache的maxCapacity應該聲明為volatile,而不是transient。
      
       最簡單的LRU算法實現(xiàn),就是利用jdk的LinkedHashMap,覆寫其中的removeEldestEntry(Map.Entry)方法即可,如下所示:
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.LinkedHashMap;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    import java.util.Map;


    /**
     * 類說明:利用LinkedHashMap實現(xiàn)簡單的緩存, 必須實現(xiàn)removeEldestEntry方法,具體參見JDK文檔
     * 
     * 
    @author dennis
     * 
     * 
    @param <K>
     * 
    @param <V>
     
    */
    public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {
        
    private final int maxCapacity;

        
    private static final float DEFAULT_LOAD_FACTOR = 0.75f;

        
    private final Lock lock = new ReentrantLock();

        
    public LRULinkedHashMap(int maxCapacity) {
            
    super(maxCapacity, DEFAULT_LOAD_FACTOR, true);
            
    this.maxCapacity = maxCapacity;
        }

        @Override
        
    protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
            
    return size() > maxCapacity;
        }
        @Override
        
    public boolean containsKey(Object key) {
            
    try {
                lock.lock();
                
    return super.containsKey(key);
            } 
    finally {
                lock.unlock();
            }
        }

        
        @Override
        
    public V get(Object key) {
            
    try {
                lock.lock();
                
    return super.get(key);
            } 
    finally {
                lock.unlock();
            }
        }

        @Override
        
    public V put(K key, V value) {
            
    try {
                lock.lock();
                
    return super.put(key, value);
            } 
    finally {
                lock.unlock();
            }
        }

        
    public int size() {
            
    try {
                lock.lock();
                
    return super.size();
            } 
    finally {
                lock.unlock();
            }
        }

        
    public void clear() {
            
    try {
                lock.lock();
                
    super.clear();
            } 
    finally {
                lock.unlock();
            }
        }

        
    public Collection<Map.Entry<K, V>> getAll() {
            
    try {
                lock.lock();
                
    return new ArrayList<Map.Entry<K, V>>(super.entrySet());
            } 
    finally {
                lock.unlock();
            }
        }
    }
        如果你去看LinkedHashMap的源碼可知,LRU算法是通過雙向鏈表來實現(xiàn),當某個位置被命中,通過調(diào)整鏈表的指向?qū)⒃撐恢谜{(diào)整到頭位置,新加入的內(nèi)容直接放在鏈表頭,如此一來,最近被命中的內(nèi)容就向鏈表頭移動,需要替換時,鏈表最后的位置就是最近最少使用的位置。
        LRU算法還可以通過計數(shù)來實現(xiàn),緩存存儲的位置附帶一個計數(shù)器,當命中時將計數(shù)器加1,替換時就查找計數(shù)最小的位置并替換,結(jié)合訪問時間戳來實現(xiàn)。這種算法比較適合緩存數(shù)據(jù)量較小的場景,顯然,遍歷查找計數(shù)最小位置的時間復雜度為O(n)。我實現(xiàn)了一個,結(jié)合了訪問時間戳,當最小計數(shù)大于MINI_ACESS時(這個參數(shù)的調(diào)整對命中率有較大影響),就移除最久沒有被訪問的項:
    package net.rubyeye.codelib.util.concurrency.cache;

    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.concurrent.atomic.AtomicLong;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;

    /**
     * 
     * 
    @author dennis 類說明:當緩存數(shù)目不多時,才用緩存計數(shù)的傳統(tǒng)LRU算法
     * 
    @param <K>
     * 
    @param <V>
     
    */
    public class LRUCache<K, V> implements Serializable {

        
    private static final int DEFAULT_CAPACITY = 100;

        
    protected Map<K, ValueEntry> map;

        
    private final ReadWriteLock lock = new ReentrantReadWriteLock();

        
    private final Lock readLock = lock.readLock();

        
    private final Lock writeLock = lock.writeLock();

        
    private final volatile int maxCapacity;  //保持可見性

        
    public static int MINI_ACCESS = 5;

        
    public LRUCache() {
            
    this(DEFAULT_CAPACITY);
        }

        
    public LRUCache(int capacity) {
            
    if (capacity <= 0)
                
    throw new RuntimeException("緩存容量不得小于0");
            
    this.maxCapacity = capacity;
            
    this.map = new HashMap<K, ValueEntry>(maxCapacity);
        }

        
    public boolean ContainsKey(K key) {
            
    try {
                readLock.lock();
                
    return this.map.containsKey(key);
            } 
    finally {
                readLock.unlock();
            }
        }

        
    public V put(K key, V value) {
            
    try {
                writeLock.lock();
                
    if ((map.size() > maxCapacity - 1&& !map.containsKey(key)) {
                    
    // System.out.println("開始");
                    Set<Map.Entry<K, ValueEntry>> entries = this.map.entrySet();
                    removeRencentlyLeastAccess(entries);
                }
                ValueEntry new_value 
    = new ValueEntry(value);
                ValueEntry old_value 
    = map.put(key, new_value);
                
    if (old_value != null) {
                    new_value.count 
    = old_value.count;
                    
    return old_value.value;
                } 
    else
                    
    return null;
            } 
    finally {
                writeLock.unlock();
            }
        }

        
    /**
         * 移除最近最少訪問
         
    */
        
    protected void removeRencentlyLeastAccess(
                Set
    <Map.Entry<K, ValueEntry>> entries) {
            
    // 最小使用次數(shù)
            long least = 0;
            
    // 訪問時間最早
            long earliest = 0;
            K toBeRemovedByCount 
    = null;
            K toBeRemovedByTime 
    = null;
            Iterator
    <Map.Entry<K, ValueEntry>> it = entries.iterator();
            
    if (it.hasNext()) {
                Map.Entry
    <K, ValueEntry> valueEntry = it.next();
                least 
    = valueEntry.getValue().count.get();
                toBeRemovedByCount 
    = valueEntry.getKey();
                earliest 
    = valueEntry.getValue().lastAccess.get();
                toBeRemovedByTime 
    = valueEntry.getKey();
            }
            
    while (it.hasNext()) {
                Map.Entry
    <K, ValueEntry> valueEntry = it.next();
                
    if (valueEntry.getValue().count.get() < least) {
                    least 
    = valueEntry.getValue().count.get();
                    toBeRemovedByCount 
    = valueEntry.getKey();
                }
                
    if (valueEntry.getValue().lastAccess.get() < earliest) {
                    earliest 
    = valueEntry.getValue().count.get();
                    toBeRemovedByTime 
    = valueEntry.getKey();
                }
            }
            
    // System.out.println("remove:" + toBeRemoved);
            
    // 如果最少使用次數(shù)大于MINI_ACCESS,那么移除訪問時間最早的項(也就是最久沒有被訪問的項)
            if (least > MINI_ACCESS) {
                map.remove(toBeRemovedByTime);
            } 
    else {
                map.remove(toBeRemovedByCount);
            }
        }

        
    public V get(K key) {
            
    try {
                readLock.lock();
                V value 
    = null;
                ValueEntry valueEntry 
    = map.get(key);
                
    if (valueEntry != null) {
                    
    // 更新訪問時間戳
                    valueEntry.updateLastAccess();
                    
    // 更新訪問次數(shù)
                    valueEntry.count.incrementAndGet();
                    value 
    = valueEntry.value;
                }
                
    return value;
            } 
    finally {
                readLock.unlock();
            }
        }

        
    public void clear() {
            
    try {
                writeLock.lock();
                map.clear();
            } 
    finally {
                writeLock.unlock();
            }
        }

        
    public int size() {
            
    try {
                readLock.lock();
                
    return map.size();
            } 
    finally {
                readLock.unlock();
            }
        }

        
    public long getCount(K key) {
            
    try {
                readLock.lock();
                ValueEntry valueEntry 
    = map.get(key);
                
    if (valueEntry != null) {
                    
    return valueEntry.count.get();
                }
                
    return 0;
            } 
    finally {
                readLock.unlock();
            }
        }

        
    public Collection<Map.Entry<K, V>> getAll() {
            
    try {
                readLock.lock();
                Set
    <K> keys = map.keySet();
                Map
    <K, V> tmp = new HashMap<K, V>();
                
    for (K key : keys) {
                    tmp.put(key, map.get(key).value);
                }
                
    return new ArrayList<Map.Entry<K, V>>(tmp.entrySet());
            } 
    finally {
                readLock.unlock();
            }
        }

        
    class ValueEntry implements Serializable {
            
    private V value;

            
    private AtomicLong count;

            
    private AtomicLong lastAccess;

            
    public ValueEntry(V value) {
                
    this.value = value;
                
    this.count = new AtomicLong(0);
                lastAccess 
    = new AtomicLong(System.nanoTime());
            }

            
    public void updateLastAccess() {
                
    this.lastAccess.set(System.nanoTime());
            }

        }
    }




    評論

    # re: 簡單LRU算法實現(xiàn)緩存-update1  回復  更多評論   

    2007-09-30 10:04 by sitinspring
    Mark.

    # re: 簡單LRU算法實現(xiàn)緩存-update1  回復  更多評論   

    2007-10-13 03:07 by 小飛飛
    這個怎么用了?

    # re: 簡單LRU算法實現(xiàn)緩存-update1  回復  更多評論   

    2007-10-13 16:43 by dennis
    @小飛飛
    怎么用?老大,緩存怎么用

    # re: 簡單LRU算法實現(xiàn)緩存-update1  回復  更多評論   

    2008-01-09 13:57 by zhangwei
    很好,我正想找一個這樣的程序那,謝謝了。

    # re: 簡單LRU算法實現(xiàn)緩存-update1[未登錄]  回復  更多評論   

    2008-01-14 09:18 by bruce
    說一下咱用呀?樓主
    主站蜘蛛池模板: 亚洲综合久久一本伊伊区| 美女啪啪网站又黄又免费| 在线播放高清国语自产拍免费| 婷婷亚洲综合五月天小说在线| 国产亚洲精品看片在线观看| 1区2区3区产品乱码免费| 337p日本欧洲亚洲大胆人人| 亚洲香蕉成人AV网站在线观看| 噼里啪啦免费观看高清动漫4 | 亚洲丁香婷婷综合久久| 国产精品亚洲精品日韩已方| 亚洲综合免费视频| EEUSS影院WWW在线观看免费 | 国产AV无码专区亚洲AV蜜芽| 亚洲av综合av一区| 免费观看四虎精品国产永久| 亚洲精品免费视频| 美女裸免费观看网站| 亚洲精品第五页中文字幕| 亚洲男人av香蕉爽爽爽爽| 无码国产精品一区二区免费 | 亚洲经典千人经典日产| 精品久久香蕉国产线看观看亚洲| 女性无套免费网站在线看| 99精品视频在线观看免费播放| 免费在线观看一区| 亚洲AV无码乱码麻豆精品国产| 亚洲精品乱码久久久久久| 国产精品四虎在线观看免费| 18禁美女黄网站色大片免费观看| caoporn成人免费公开| 亚洲国产成人精品无码区花野真一 | 91精品国产免费| 久久免费观看视频| 特级aaaaaaaaa毛片免费视频| 亚洲一卡2卡4卡5卡6卡残暴在线| 国产亚洲综合成人91精品| 亚洲国产aⅴ综合网| 日本免费人成视频播放| 18国产精品白浆在线观看免费| 一级毛片免费观看不卡的|