LRU缓存淘汰

LRU缓存淘汰是redis中的一种淘汰策略, 当内存大小不足以存放数据时, 此时存入新数据, 将删除较早存入的数据.
在dubbo中使用LRU来缓存 hostName.
在mysql中使用LRU来缓存 serverSideStatementCheckCache 和 serverSideStatementCache.

代码实现
  1. package com.ipaynow.tool.lru;
  2. import java.util.LinkedHashMap;
  3. import java.util.Map;
  4. import java.util.concurrent.locks.Lock;
  5. import java.util.concurrent.locks.ReentrantLock;
  6. /**
  7. * 基于LinkedHashMap LRU 缓存淘汰, 以下框架中都有使用
  8. * dubbo com.alibaba.dubbo.common.utils.LRUCache
  9. * com.mysql.jdbc.util.LRUCache
  10. *
  11. * @author liuzhihang
  12. * @date 2018/11/20 10:43
  13. */
  14. public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {
  15. /**
  16. * 设置最大容量
  17. */
  18. private volatile int maxCapacity;
  19. private static final int DEFAULT_MAX_CAPACITY = 1000;
  20. private static final float DEFAULT_LOAD_FACTOR = 0.75f;
  21. private final Lock lock = new ReentrantLock();
  22. public LRULinkedHashMap() {
  23. this.maxCapacity = DEFAULT_MAX_CAPACITY;
  24. }
  25. public LRULinkedHashMap(int maxCapacity) {
  26. // accessOrder设置为true 按照时间排序
  27. super(maxCapacity, DEFAULT_LOAD_FACTOR, true);
  28. this.maxCapacity = maxCapacity;
  29. }
  30. /**
  31. * 当链表长度大于最大容量时 删除最旧的元素
  32. */
  33. @Override
  34. protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
  35. return size() > maxCapacity;
  36. }
  37. @Override
  38. public boolean containsKey(Object key) {
  39. try {
  40. lock.lock();
  41. return super.containsKey(key);
  42. } finally {
  43. lock.unlock();
  44. }
  45. }
  46. @Override
  47. public V get(Object key) {
  48. try {
  49. lock.lock();
  50. return super.get(key);
  51. } finally {
  52. lock.unlock();
  53. }
  54. }
  55. @Override
  56. public V put(K key, V value) {
  57. try {
  58. lock.lock();
  59. return super.put(key, value);
  60. } finally {
  61. lock.unlock();
  62. }
  63. }
  64. @Override
  65. public V remove(Object key) {
  66. try {
  67. lock.lock();
  68. return super.remove(key);
  69. } finally {
  70. lock.unlock();
  71. }
  72. }
  73. @Override
  74. public int size() {
  75. try {
  76. lock.lock();
  77. return super.size();
  78. } finally {
  79. lock.unlock();
  80. }
  81. }
  82. @Override
  83. public void clear() {
  84. try {
  85. lock.lock();
  86. super.clear();
  87. } finally {
  88. lock.unlock();
  89. }
  90. }
  91. public int getMaxCapacity() {
  92. return maxCapacity;
  93. }
  94. public void setMaxCapacity(int maxCapacity) {
  95. this.maxCapacity = maxCapacity;
  96. }
  97. }

测试代码及结果
  1. package com.ipaynow.tool.lru;
  2. import java.time.LocalDateTime;
  3. import java.time.format.DateTimeFormatter;
  4. import java.util.Iterator;
  5. import java.util.Map;
  6. /**
  7. * @author liuzhihang
  8. * @date 2018/11/20 10:58
  9. */
  10. public class LRUTest {
  11. public static void main(String[] args) throws InterruptedException {
  12. LRULinkedHashMap<String, String> map = new LRULinkedHashMap<>(5);
  13. for (int i = 0; i < 10; i++) {
  14. Thread.sleep(1000);
  15. map.put(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss SSS")), "value" + i);
  16. }
  17. for (Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator(); iterator.hasNext(); ) {
  18. Map.Entry<String, String> entry = iterator.next();
  19. String key = entry.getKey();
  20. String value = entry.getValue();
  21. System.out.println(key + "------------" + value);
  22. }
  23. }
  24. }

控制台输出结果:

  1. 2018-11-20 11:13:21 398------------value5
  2. 2018-11-20 11:13:22 399------------value6
  3. 2018-11-20 11:13:23 400------------value7
  4. 2018-11-20 11:13:24 400------------value8
  5. 2018-11-20 11:13:25 400------------value9
  6. Process finished with exit code 0