# sinrycache **Repository Path**: isinry/sinrycache ## Basic Information - **Project Name**: sinrycache - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-12-12 - **Last Updated**: 2021-12-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 一、作业内容 动手实现一个Cache对象或组件或服务,带超时淘汰功能。 补充说明:
(0)用Java语言实现,JDK版本任意。其他语言也欢迎交流。
(1)支持多线程。
(2)描述设计过程。
(3)输出性能测试报告。
# 二、设计描述 1)实现内容:缓存操作,锁策略,缓存命中记录器,缓存序列化策略,淘汰策略
2)设计模式:**责任链模式**,使用该模式目的是为了更好的动态扩展策略
![image.png](img_1.png) ## 1. 超时淘汰机制 - 写入缓存时,由淘汰策略存储key的过期时间 - 当写入新的缓存超过负载数量size时,由ExpireLinkedHashMap取出并计算最旧的条目是否过期,过期则删除缓存 ## 2. 存储器 存储器使用ConcurrentHashMap作为缓存 # 三、性能测试 > ![image.png](img_2.png)
> JDK1.8
> 使用parallelStream内置的ForkJoinPool线程池,默认数量20个 ### 1. 多线程测试 - 测试代码 ```java @Test public void test1() { List list = new ArrayList<>(); for (int i = 1; i <= 1000000; i++) { list.add(i); } System.out.println("写入测试 >>>"); long startTime = System.currentTimeMillis(); list.parallelStream().forEach(i -> { cache.set("name_" + i, "sinry_" + i); System.out.println(i); }); long endTime = System.currentTimeMillis(); long result = endTime - startTime; System.out.println("写入结果:" + list.size() + "个"); System.out.println("执行耗时:"+result+"ms"); System.out.println("========================"); System.out.println("读取测试 >>>"); long readStartTime = System.currentTimeMillis(); List collect = list.parallelStream().peek(i -> cache.get("name_" + i)) .collect(Collectors.toList()); long readEndTime = System.currentTimeMillis(); long readResult = readEndTime - readStartTime; System.out.println("读取结果:" + collect.size() + "个"); System.out.println("执行耗时:"+readResult+"ms"); } ``` - 运行结果 ```java 写入测试 >>> 写入结果:1000000个 执行耗时:1899ms ======================== 读取测试 >>> 读取结果:1000000个 执行耗时:1349ms ``` ### 2. 单线程测试 - 测试代码 ```java @Test public void test1() { List list = new ArrayList<>(); for (int i = 1; i <= 1000000; i++) { list.add(i); } System.out.println("写入测试 >>>"); long startTime = System.currentTimeMillis(); list.forEach(i -> cache.set("name_" + i, "sinry_" + i)); long endTime = System.currentTimeMillis(); long result = endTime - startTime; System.out.println("写入结果:" + list.size() + "个"); System.out.println("执行耗时:"+result+"ms"); System.out.println("========================"); System.out.println("读取测试 >>>"); long readStartTime = System.currentTimeMillis(); List collect = list.stream().peek(i -> cache.get("name_" + i)) .collect(Collectors.toList()); long readEndTime = System.currentTimeMillis(); long readResult = readEndTime - readStartTime; System.out.println("读取结果:" + collect.size() + "个"); System.out.println("执行耗时:"+readResult+"ms"); } ``` - 测试结果 ```java 写入测试 >>> 写入结果:1000000个 执行耗时:1581ms ======================== 读取测试 >>> 读取结果:1000000个 执行耗时:943ms ``` ### 3. 测试总结 - 模拟并发写入和读取测试 - 受限于机器内存,写入大量数据则会内存不足导致OOM - 多线程测试 - 多线程比单线程慢,是因为M1的单核处理能力要比多核处理快😅 # 四、优缺点 - 优点 - 动态扩展策略,应用层可自由配置策略 - 缺点 - 存储器由hashmap实现,有相对局限性 - 淘汰策略不支持自动到期淘汰,目前只可以读取时计算到期时间, 需要用到定时器处理。 - 随着策略模式的扩展也会对性能有损耗