高并发实战1---手写计算器缓存

实现思路

  • 定义一个用于计算功能的顶级接口 ,在接口类定义,计算的接口
  • 具体的计算器 ,都去实现这个接口
  • 定义个带有“记忆”功能(缓存)的计算的容器,通过构造方法传递具体的计算器
  • 通过ConcurrentHashMap 去缓存计算的入参结果
  • 每次计算的时候判断是否有结果已经缓存,有则跳过计算,直接获取上一次的计算结果

顶层类:computale 接口, 定义为函数式接口

package com.ljq.mydemo.thread.compute;

/**
 *
 * 定义计算的接口
 *包含一个 用户计算的函数式接口
 * @author gino
 * 2021-11-17
 */
public interface Computable<A,V> {

    /**
     * 定义函数式接口
     * @param ags
     * @return
     * @throws InterruptedException
     */
    public V compute(A ags) throws InterruptedException;
}

定义带缓存的计算器容器

package com.ljq.mydemo.thread.compute;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 初级demo     但是这样也会同时也会存在一定的局限性
 * (就是当一个线程正在计算的时候,另外一个线程发现缓存中没有结果, 此时也会去计算,这样其实就会出现计算两次相同的结果
 * 如果计算的时间很长,就会浪费一部分时间  ,而我们理想的状态应该是只计算一次就行了,如果发现有线程在计算结果了,当前的线程不应该继续计算
 * 而是,等待前一个线程的计算结果[这才是最明智的选择]
 *
 *在这个问题将会在下一个版本(博客) 介绍
 * )
 *
 *
 * <p>
 * 实现一个带有 “记忆”  功能计算接口
 * 该接口是使用于  多线程 ,计算费时长  的任务
 * <p>
 * A  参与计算的参数
 * V  参与计算的结果
 *
 * @author gino
 * 2021-11-17
 */
public class MemoryCompute<A, V> implements Computable<A, V> {
    /**
     * 为了保证并发线程安全,以及线程安全的效率
     * 所用采用ConcurrentHashMap  而不是采用synchronized
     * 因为ConcurrentHashMap 采用的是分段锁, 而synchronized 会锁住整个方法
     * <p>
     * 缓存计算参数以及计算接口
     */
    private final Map<A, V> cache = new ConcurrentHashMap<A, V>();

    /**
     * 定义计算的计算器,计算器通过构造函数传递
     */
    private final Computable<A, V> computable;


    public MemoryCompute(Computable<A, V> computable) {
        this.computable = computable;
    }

    @Override
    public V compute(A ags) throws InterruptedException {
        //先读取缓存
        V result = cache.get(ags);
        System.out.println(Thread.currentThread().getId()+": get cache value : "+result  + " key is "+ags);
        if (Objects.isNull(result)) {
            System.out.println(Thread.currentThread().getName()+": get cache fail ,is computing.......");
            //缓存为空则需要重新计算
            result = computable.compute(ags);
            //将计算结果加入缓存
            cache.put(ags, result);
        }
        return result;
    }
}

测试

package com.ljq.mydemo.thread.compute;

import java.math.BigInteger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author gino
 * 2021-11-17
 */
public class ComputeTest001 {


    public static void main(String[] args) throws InterruptedException {
        //实例具体的计算方法
        ExampleCompute compute=new ExampleCompute();
        //实例化到计算的容器
        MemoryCompute<String, BigInteger> memoryCompute=new MemoryCompute(compute);


        //创建带缓存的线程池
        ExecutorService services = Executors.newCachedThreadPool();
        //模拟多线程访问
        for (int i = 0; i <5 ; i++) {

                    System.out.println("create randomNumber: "+6);
                    memoryCompute.compute(String.valueOf(6));

        }
        //关闭数据库连接池
        services.shutdown();

    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值