Java本地缓存的实现代码

作者:Lis`s Blog 时间:2022-02-22 11:21:04 

使用场景

Java 应用中,对于访问频率高,更新少的数据,通常的方案是将这类数据加入缓存中。相对从数据库中读取来说,读缓存效率会有很大提升。

在集群环境下,常用的分布式缓存有 Redis 、 Memcached 等。但在某些业务场景上,可能不需要去搭建一套复杂的分布式缓存系统,在单机环境下,通常是会希望使用内部的缓存( LocalCache )。

实现

这里提供了两种 LocalCache 的实现,一种是基于 ConcurrentHashMap 实现基本本地缓存,另外一种是基于 LinkedHashMap 实现 LRU 策略的本地缓存。

基于ConcurrentHashMap的实现


static {
 timer = new Timer();
 map = new ConcurrentHashMap<>();
}

ConcurrentHashMap 作为缓存的存储结构。因为 ConcurrentHashMap 的线程安全的,所以基于此实现的 LocalCache 在多线程并发环境的操作是安全的。在 JDK1.8 中, ConcurrentHashMap 是支持完全并发读,这对本地缓存的效率也是一种提升。通过调用 ConcurrentHashMap map 的操作来实现对缓存的操作。

私有构造函数


privateLocalCache(){

}

LocalCache 是工具类,通过私有构造函数强化不可实例化的能力。

缓存清除机制


/**
* 清除缓存任务类
*/
static classCleanWorkerTaskextendsTimerTask{

private String key;

publicCleanWorkerTask(String key){
    this.key = key;
  }

publicvoidrun(){
    LocalCache.remove(key);
  }
}

清理失效缓存是由 Timer 类实现的。内部类 CleanWorkerTask 继承于 TimerTask 用户清除缓存。每当新增一个元素的时候,都会调用 timer.schedule 加载清除缓存的任务。

基于LinkedHashMap的实现

LinkedHashMap 作为缓存的存储结构。主要是通过 LinkedHashMap 的按照访问顺序的特性来实现 LRU 策略。

LRU

LRU Least Recently Used 的缩写,即最近最久未使用。 LRU 缓存将会利用这个算法来淘汰缓存中老的数据元素,从而优化内存空间。

基于LRU策略的map

这里利用 LinkedHashMap 来实现基于 LRU 策略的 map 。通过调用父类 LinkedHashMap 的构造函数来实例化 map 。参数 accessOrder 设置为 true 保证其可以实现 LRU 策略。


static classLRUMap<K,V>extendsLinkedHashMap<K,V>{

... // 省略部分代码

publicLRUMap(intinitialCapacity,floatloadFactor){
     super(initialCapacity, loadFactor, true);
   }

... // 省略部分代码

/**
    * 重写LinkedHashMap中removeEldestEntry方法;
    * 新增元素的时候,会判断当前map大小是否超过DEFAULT_MAX_CAPACITY,超过则移除map中最老的节点;
    *
    * @param eldest
    * @return
    */
   protectedbooleanremoveEldestEntry(Map.Entry<K, V> eldest){
     return size() > DEFAULT_MAX_CAPACITY;
   }

}

线程安全


/**
* 读写锁
*/
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

private final Lock rLock = readWriteLock.readLock();

private final Lock wLock = readWriteLock.writeLock();

LinkedHashMap 并不是线程安全,如果不加控制的在多线程环境下使用的话,会有问题。所以在 LRUMap 中引入了 ReentrantReadWriteLock 读写锁,来控制并发问题。

缓存淘汰机制


protectedbooleanremoveEldestEntry(Map.Entry<K, V> eldest){
 return size() > DEFAULT_MAX_CAPACITY;
}

此处重写 LinkedHashMap removeEldestEntry 方法, 当缓存新增元素的时候,会判断当前 map 大小是否超过 DEFAULT_MAX_CAPACITY ,超过则移除map中最老的节点。

缓存清除机制

缓存清除机制与 ConcurrentHashMap 的实现一致,均是通过 timer 实现。

源码地址: GitHub 

来源:http://lishuo.me/2017/05/05/Java%E6%9C%AC%E5%9C%B0%E7%BC%93%E5%AD%98%E7%9A%84%E5%AE%9E%E7%8E%B0/?utm_source=tuicool&utm_medium=referral

标签:java,本地,缓存
0
投稿

猜你喜欢

  • springboot项目启动的时候参数无效的解决

    2022-09-03 14:50:29
  • Java实现json数据处理的常用脚本分享

    2022-07-27 15:21:39
  • ReentrantLock源码详解--公平锁、非公平锁

    2023-04-22 17:18:56
  • C#中事件的定义和使用

    2022-02-15 13:34:00
  • java基础之数组常用操作总结(必看篇)

    2022-12-09 03:32:17
  • Android使用FontMetrics对象计算位置坐标

    2023-02-06 15:35:20
  • android创建数据库(SQLite)保存图片示例

    2023-07-11 23:07:14
  • Java多线程常见案例分析线程池与单例模式及阻塞队列

    2022-06-01 06:42:42
  • 在maven中引入本地jar包的步骤

    2023-11-25 10:43:44
  • 利用C#实现SSLSocket加密通讯的方法详解

    2023-03-01 02:23:05
  • Android编程简单实现九宫格示例

    2021-12-06 21:43:57
  • 一文搞懂c# await,async执行流

    2023-07-14 01:22:35
  • Java序列化JSON丢失精度问题的解决方法(修复Long类型太长)

    2022-10-15 00:01:34
  • C#线程同步的三类情景分析

    2023-01-07 22:38:04
  • 详解Java面向对象中的继承

    2023-10-06 13:26:14
  • QT实现QML侧边导航栏的最简方法

    2021-09-17 02:54:35
  • 解决SpringBoot web项目启动后立即关闭的问题

    2023-07-26 02:33:37
  • SpringBoot集成Swagger构建api文档的操作

    2023-11-03 09:13:51
  • Java实现有限状态机的推荐方案分享

    2022-01-07 15:54:27
  • 运行java的class文件方法详解

    2021-07-29 03:53:48
  • asp之家 软件编程 m.aspxhome.com