缓存实现思路(代码片段)

jinshuai86 jinshuai86     2022-12-21     277

关键词:

缓存主要为了解决各个组件之间读取速度不匹配问题,比如寄存器是L1的缓存,L1是L2的缓存,L2是L3的缓存,L3是内存的缓存等。通过读Java Concurrency Practice P85,实现了一个简单可以添加和获取数据的缓存。其它的诸如缓存过期,更新缓存等没有实现- -!!

代码

计算接口,用到了装饰者模式。


public interface Computable<A,V> 
    V compute(A arg);

一种计算的实现

public class ExpensiveFunction implements Computable<String,BigInteger> 

    @Override
    public BigInteger compute(String arg) 
       // 经过长时间计算后
        try 
            Thread.sleep(500000);           
         catch (InterruptedException ie) 

        
        return new BigInteger(arg); 
    

版本1

通过HashMap时间复杂度为O(1)的特性以及synchronized保证线程安全来构建缓存


public class MyCacheV1<A,V> implements Computable<A,V>

    private Map<A,V> cache = new HashMap<>();
    private Computable computable;

    public MyCacheV1(Computable computable) 
        this.computable = computable;
    

    @Override
    public synchronized V compute(A arg) 
        V result = cache.get(arg);
        if (result == null) 
            result = (V)computable.compute(arg);
            cache.put(arg,result);
        
        return result;
    

版本2

版本1添加了synchronized,多线程情况下造成性能下降 -> 换成ConcurrentHashMap

public class MyCacheV2<A,V> implements Computable<A,V>

    private Map<A,V> cache = new ConcurrentHashMap<>();
    private Computable computable;

    public MyCacheV2(Computable computable) 
        this.computable = computable;
    

    @Override
    public V compute(A arg) 
        V result = cache.get(arg);
        if (result == null) 
            result = (V)computable.compute(arg);
            cache.put(arg,result);
        
        return result;
    

版本3

版本2先判断 -> 在计算属于复合操作而且没有加锁导致线程不安全会产生重读计算。如果遇到计算时间非常长的计算,一旦重复会消耗大量的资源。
解决思路:如果其他线程正在计算目标值,当前线程阻塞直到其它线程计算出结果返回即可。
实现:通过FutureTask的get()方法。如果没有结果,会阻塞当前线程。

public class MyCacheV3<A,V> implements Computable<A,V>

    private Map<A,FutureTask> cache = new ConcurrentHashMap<>();
    private Computable computable;

    public MyCacheV3(Computable computable) 
        this.computable = computable;
    

    @Override
    public V compute(A arg) 
        Future future = cache.get(arg);
        if (future == null) 
            FutureTask futureTask = new FutureTask(new Callable() 
                @Override
                public V call() throws Exception 
                    return (V)computable.compute(arg);
                
            );
            // 用到了ConcurrentHashMap的原子操作
            future = cache.putIfAbsent(arg,futureTask);
            // 二次判断
            if (future == null) future = futureTask; futureTask.run();
        
        V result = null;
        try 
            result = (V) future.get();
         catch (InterruptedException e) 
            e.printStackTrace();
         catch (ExecutionException e) 
            e.printStackTrace();
        
        return result;
    



面试官:redis如何实现每周热评功能?说说思路!(代码片段)

思路分析做每周热议,应该用缓存来做,如果直接查库的话,会对数据库造成压力。用缓存做的话,用Redis来做缓存的话比较合适一点。#利用Redsi添加数据命令#day:1指的是在1号的时候post:1第一篇文章添加了10条评... 查看详情

编程实践关于应用层的本地内存缓存框架的代码实现(代码片段)

文章目录用golang实现一个线程安全的本地缓存框架,给出具体的代码实例。一、准备工作1.1定义必要的数据结构二、实现逻辑2.1设置缓存项2.2获取缓存项2.3删除缓存项用Java实现一个线程安全的本地缓存框架,给出具体的代码实... 查看详情

基于信号量与环形队列实现读写异步缓存队列(代码片段)

...思路三、示例代码一、需求      实现一个读写异步的缓存队列,主要实现功能如下:    1、缓存队列作为临界资源,要是线程安全的,不会出现读线程与写线程同时操作缓存队列的情况发生。    2、当缓... 查看详情

redis缓存简介以及缓存的更新策略(代码片段)

目录一、什么是缓存二、为什么要使用缓存三、如何使用缓存四、添加商户缓存1、缓存模型和思路 2、代码如下五、缓存更新策略 1、数据库缓存不一致解决方案: 2、数据库和缓存不一致采用什么方案3、CacheAsidePattern实现... 查看详情

java从零开始手写redislru缓存淘汰策略详解(代码片段)

前言java从零手写实现redis(一)如何实现固定大小的缓存?java从零手写实现redis(三)redisexpire过期原理java从零手写实现redis(三)内存数据如何重启不丢失?java从零手写实现redis(四)添加监听器java从零手写实现redis(五)过... 查看详情

java实现lru缓存算法(代码片段)

Java实现LRU缓存算法 一、什么是LRULRU(LeastRecentlyUsed,最近最少使用)是一种缓存算法,其核心思想是将最近最少使用的缓存项移除,以便为更常用的缓存项腾出空间。在实际应用中,LRU算法被广泛用于缓存和页面置换。 ... 查看详情

react实现网站换肤功能(代码片段)

...主题色的样式文件;  2.将用户的选择记录在本地缓存中;  3.每次进入应用时,读取缓存,根据缓存的信息判断要加载哪个样式文件即可;三.具体实现思路1.准备四个对应不同主题色的样式文件:![](https://images2018 查看详情

elasticsearchelasticsearch缓存策略querycacheingpolicy(代码片段)

1.概述在ES里,QueryCacheingPolicy的默认实现是UsageTrackingQueryCachingPolicy。该Policy的基本思路是根据使用频率决定是否缓存。对于构建成本较高的索引,比如MultiTermQuery,MultiTermQueryConstantScoreWrapper,TermInSetQuery&# 查看详情

假装优雅地实现定时缓存装饰器(代码片段)

...工匠:使用装饰器的技巧一日一技:实现有过期时间的LRU缓存这次的参考资料写在前面,因为写得真不错!开始阅读本篇分享前,建议先阅读参考资料,如果还不能实现定时缓存装饰器,再继续从这里开始读。实现思路功能拆分... 查看详情

lru基本介绍及其实现方式(代码片段)

...eee85f0203001e9bc34f65b4参考LRU算法dubbo-cache一.基本介绍1.1常见缓存淘汰算法及其实现思路对于缓存,常见淘汰算法有3:FIFO:firstinfirstout,先进先出,即假定刚刚加入的数据总会被访问到;LRU:leastrecentlyused,最近最少使用, 查看详情

排行榜的简单设计思路(代码片段)

前言基于mysqlSELECTORDERBY加索引加缓存借助redis实时排行榜实现原理为什么Redis要用跳表来实现有序集合,而不是红黑树?参考TOC前言排行榜几乎已经成为互联网应用中的必备模块,特别是游戏领域,它是对某一相关同类事物的客... 查看详情

mysql的查询缓存参数介绍与优化思路(代码片段)

...实数据,可以自己做个计算还是挺有趣的!查询缓存的参数说明(my.cnf)mysql>showglobalvariableslike"query_cache%";Va 查看详情

基于信号量与环形队列实现读写异步缓存队列(代码片段)

...思路三、示例代码一、需求      实现一个读写异步的缓存队列,主要实现功能如下:    1、缓存队列作为临界资源,要是线程安全的,不会出现读线程与写线程同时操作缓存队列的情况发生。    2、当缓... 查看详情

场景应用:自己设计一个本地缓存(代码实现)(代码片段)

...5.线程安全6.简明的接口7.是否持久化8.阻塞机制代码实战缓存元素CacheElement实现清除策略LRULinkedHashMap实现缓存接口MyCache实现我的本地缓存实现MyLocalCache实现代码测试想要设计一 查看详情

场景应用:自己设计一个本地缓存(代码实现)(代码片段)

...5.线程安全6.简明的接口7.是否持久化8.阻塞机制代码实战缓存元素CacheElement实现清除策略LRULinkedHashMap实现缓存接口MyCache实现我的本地缓存实现MyLocalCache实现代码测试想要设计一 查看详情

lru实现缓存(代码片段)

LRU:LeastRecentlyused最近最少使用 1.使用LinkedHashMap实现inheritance实现方式继承map类可以使用Collections.synchronizedMap方式实现线程安全的操作publicclassLruCache<K,V>extendsLinkedHashMap<K,V>privatefinalintMAX_CACH 查看详情

.netcorewebapi利用iactionfilter实现请求缓存(代码片段)

.NetCoreWebAPI利用IActionFilter实现请求缓存本文使用Redis缓存方式1新建类首先新建一个缓存类CustomActionCacheAttribute继承Attribute,因为需要给方法做标记。再引用并实现IActionFilter接口publicclassCustomActionCacheAttribute:Attribute,IActionFilter 查看详情

javascriptnetlify上的缓存sqip实现(代码片段)

查看详情