一:LRU算法
? ? ? LRU即最近最少使用算法,常用在缓存淘汰机制里面,目前比较流行的基于内存的分布式缓存系统memcached默认就是使用LRU算法来对过期的数据进 行淘汰,比如假定我们设置缓存最多存1000条数据,当数据未达到1000条时可以一直添加,但数据超过1000条了就会使用采用的缓存淘汰算法淘汰过期 的数据。
二:链表实现原理
? ? ? 下 面的图片是在网上找的一张。原理很简单,每个节点node都持有前后节点的引用,当某个节点删除时或者某个节点被访问时都需要移动链表的位置,基于LRU 的缓存算法,当某个节点被访问的时候,将这个节点移到链表头部表示最新的数据,删除的时候,直接删除链表尾部的数据即可

三:代码实现
?
- package?com.travelsky.pss.lru;??
- ??
- import?java.util.Hashtable;??
- import?java.util.concurrent.CountDownLatch;??
- import?java.util.concurrent.ExecutorService;??
- import?java.util.concurrent.Executors;??
- ??
- public?class?LRUCacheLinkHashMap<K,?V>?{??
- ??
- ????private?LinkCacheNode?firstNode;??
- ??
- ????private?LinkCacheNode?lastNode;??
- ??
- ????private?final?int?MAX_CACHE_SIZE;??
- ??
- ????private?Hashtable<K,?LinkCacheNode>?hashtable;??
- ??
- ????public?LRUCacheLinkHashMap(int?cacheSize)?{??
- ????????this.MAX_CACHE_SIZE?=?cacheSize;??
- ????????hashtable?=?new?Hashtable<K,?LinkCacheNode>(cacheSize);??
- ????}??
- ??
- ?????
- ?
- ?
- ?
- ?
- ??
- ????class?LinkCacheNode?{??
- ??????????
- ????????private?LinkCacheNode?prev;??
- ??????????
- ????????private?LinkCacheNode?next;??
- ??????????
- ????????private?K?key;??
- ??????????
- ????????private?V?value;??
- ????}??
- ??
- ??????
- ????public?synchronized?void?put(K?key,?V?value)?{??
- ??????????
- ????????LinkCacheNode?cacheNode?=?getCacheNode(key);??
- ????????if?(null?==?cacheNode)?{??
- ??????????????
- ????????????if?(hashtable.size()?>=?MAX_CACHE_SIZE)?{??
- ????????????????if?(null?!=?lastNode)?{??
- ????????????????????hashtable.remove(lastNode.key);??
- ??????????????????????
- ????????????????????removeLastNode();??
- ????????????????}??
- ????????????}??
- ????????????cacheNode?=?new?LinkCacheNode();??
- ????????}??
- ????????cacheNode.key?=?key;??
- ??????????
- ????????cacheNode.value?=?value;??
- ??????????
- ????????moveToHeadNode(cacheNode);??
- ????????hashtable.put(key,?cacheNode);??
- ????????System.out.println("当前线程:"?+?Thread.currentThread().getName()??+?",put操作:firstNode:"?+?firstNode);??
- ????????System.out.println("当前线程:"?+?Thread.currentThread().getName()?+",put操作:lastNode:"?+?lastNode);??
- ????????System.out.println("=================================================");??
- ????}??
- ??
- ?????
- ?
- ?
- ?
- ?
- ??
- ????public?synchronized?Object?get(K?key)?{??
- ????????LinkCacheNode?node?=?getCacheNode(key);??
- ????????if?(null?==?node)?{??
- ????????????return?null;??
- ????????}??
- ??????????
- ????????moveToHeadNode(node);??
- ????????System.out.println("当前线程:"?+?Thread.currentThread().getName()?+?",get操作:firstNode:"?+?firstNode);??
- ????????System.out.println("当前线程:"?+?Thread.currentThread().getName()?+?",get操作:lastNode:"?+?lastNode);??
- ????????System.out.println("================================");??
- ????????return?node.value;??
- ????}??
- ??
- ?????
- ?
- ?
- ?
- ??
- ????public?synchronized?void?remove(K?key)?{??
- ????????LinkCacheNode?entry?=?getCacheNode(key);??
- ????????if?(null?!=?entry)?{??
- ??????????????
- ????????????if?(null?!=?entry.prev)?{??
- ????????????????entry.prev.next?=?entry.next;??
- ????????????}??
- ??????????????
- ????????????if?(null?!=?entry.next)?{??
- ????????????????entry.next.prev?=?entry.prev;??
- ????????????}??
- ??????????????
- ????????????if?(entry?==?firstNode)?{??
- ????????????????firstNode?=?entry.next;??
- ????????????}??
- ??????????????
- ????????????if?(entry?==?lastNode)?{??
- ????????????????lastNode?=?entry.prev;??
- ????????????}??
- ????????}??
- ????????hashtable.remove(key);??
- ????}??
- ??
- ?????
- ?
- ?
- ??
- ????private?void?moveToHeadNode(LinkCacheNode?cacheEntry)?{??
- ??????????
- ????????if?(cacheEntry?==?firstNode)?{??
- ????????????return;??
- ????????}??
- ??????????
- ????????if?(null?!=?cacheEntry.prev)?{??
- ????????????cacheEntry.prev.next?=?cacheEntry.next;??
- ????????}??
- ????????if?(null?!=?cacheEntry.next)?{??
- ????????????cacheEntry.next.prev?=?cacheEntry.prev;??
- ????????}??
- ??????????
- ????????if?(cacheEntry?==?lastNode)?{??
- ????????????lastNode?=?cacheEntry.prev;??
- ????????}??
- ????????if?(null?!=?firstNode)?{??
- ??????????????
- ????????????cacheEntry.next?=?firstNode;??
- ??????????????
- ????????????firstNode.prev?=?cacheEntry;??
- ????????}??
- ??????????
- ????????firstNode?=?cacheEntry;??
- ????????cacheEntry.prev?=?null;??
- ????????if?(null?==?lastNode)?{??
- ????????????lastNode?=?firstNode;??
- ????????}??
- ??
- ????}??
- ??
- ?????
- ?
- ??
- ????private?void?removeLastNode()?{??
- ????????if?(null?!=?lastNode)?{??
- ????????????if?(null?!=?lastNode.prev)?{??
- ????????????????lastNode.prev.next?=?null;??
- ??????????????????
- ????????????}?else?{??
- ????????????????firstNode?=?null;??
- ????????????}??
- ????????????lastNode?=?lastNode.prev;??
- ????????}??
- ????}??
- ??
- ?????
- ?
- ?
- ?
- ?
- ??
- ????private?LinkCacheNode?getCacheNode(K?key)?{??
- ????????return?hashtable.get(key);??
- ????}??
- ??
- ????public?static?void?main(String[]?args)?throws?InterruptedException?{??
- ????????final?LRUCacheLinkHashMap<String,?String>?lru?=???
- ????????????????new?LRUCacheLinkHashMap<String,?String>(3);??
- ????????final?CountDownLatch?latch?=?new?CountDownLatch(15);??
- ????????ExecutorService?service?=?Executors.newCachedThreadPool();??
- ????????for(int?i=1;i<=15;i++){??
- ????????????final?int?index?=?i;??
- ????????????service.submit(new??Runnable()?{??
- ????????????????@Override??
- ????????????????public?void?run()?{??
- ????????????????????lru.put(String.valueOf(index),?"value:"?+?index);??
- ????????????????????latch.countDown();??
- ????????????????}??
- ????????????});??
- ????????}??
- ????????latch.await();?????????????????
- ????}??
- }??
??可能的运行结果如下:
- 当前线程:pool-1-thread-4,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@5660d6??
- 当前线程:pool-1-thread-4,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@5660d6??
- =================================================??
- 当前线程:pool-1-thread-15,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@ef83d3??
- 当前线程:pool-1-thread-15,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@5660d6??
- =================================================??
- 当前线程:pool-1-thread-14,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@88df60??
- 当前线程:pool-1-thread-14,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@5660d6??
- =================================================??
- 当前线程:pool-1-thread-13,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@1318b??
- 当前线程:pool-1-thread-13,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@ef83d3??
- =================================================??
- 当前线程:pool-1-thread-11,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@5bb966??
- 当前线程:pool-1-thread-11,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@88df60??
- =================================================??
- 当前线程:pool-1-thread-10,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@1e903d5??
- 当前线程:pool-1-thread-10,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@1318b??
- =================================================??
- 当前线程:pool-1-thread-9,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@faa550??
- 当前线程:pool-1-thread-9,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@5bb966??
- =================================================??
- 当前线程:pool-1-thread-7,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@17b6643??
- 当前线程:pool-1-thread-7,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@1e903d5??
- =================================================??
- 当前线程:pool-1-thread-6,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@76e8a7??
- 当前线程:pool-1-thread-6,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@faa550??
- =================================================??
- 当前线程:pool-1-thread-5,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@a45536??
- 当前线程:pool-1-thread-5,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@17b6643??
- =================================================??
- 当前线程:pool-1-thread-3,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@d66426??
- 当前线程:pool-1-thread-3,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@76e8a7??
- =================================================??
- 当前线程:pool-1-thread-2,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@1490eb5??
- 当前线程:pool-1-thread-2,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@a45536??
- =================================================??
- 当前线程:pool-1-thread-1,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@164b09c??
- 当前线程:pool-1-thread-1,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@d66426??
- =================================================??
- 当前线程:pool-1-thread-12,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@186f247??
- 当前线程:pool-1-thread-12,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@1490eb5??
- =================================================??
- 当前线程:pool-1-thread-8,put操作:firstNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@8c4a77??
- 当前线程:pool-1-thread-8,put操作:lastNode:com.travelsky.pss.lru.LRUCacheLinkHashMap$LinkCacheNode@164b09c??
- =================================================??
?? 可以看到,当多个线程同时往链表添加数据的时候,当超过大小3后,最先添加的数据会被淘汰掉。
基于双向链表实现LRU缓存淘汰机制
原文:http://090508tanjie.iteye.com/blog/2308782