zoukankan      html  css  js  c++  java
  • 并发编程实践第5章。使用同步工具类做一个高效且可伸缩的结果缓存

    1:使用同步工具类做一个高效且可伸缩的结果缓存

           做缓存一般使用Map结构,当想要取一个键的值时,判断是否存在。如果存在,直接取出即可,如果不存在,则为键计算一个值,将键值对添加到map中。

          现在假设我们要将一个字符串转换成整数,整数加1作为返回值,字符串作为键,返回的整数值作为值。构建一个缓存d。

        1.1首先创建一个转换接口

      

    package chapter05.class6;
    
    /**
     * 定义一个参数转换接口
     * @param <K>  被转换参数
     * @param <V>  转换参数
     */
    public interface Computable<V,K> {
        V compute(K arg) throws InterruptedException;
    }

    1.2:创建一个缓存对象

           

    package chapter05.class6;
    
    import java.util.concurrent.*;
    
    /**
     * 缓存
     */
    public class Memoizer<V,K> implements Computable<V,K> {
    
        //Future<V>相当于一个能够调用将来结果的容器,结果计算过程交由其它完成。携带结果的任务有Future.
        private final ConcurrentMap<K, Future<V>> cache = new ConcurrentHashMap<>();//使用ConcurrentMap作为缓存。
        private final Computable<V,K> c;  //转换接口
        public Memoizer(Computable<V, K> c) {
            this.c = c;
        }
    
        @Override
        public V compute(K arg) throws InterruptedException {
            while (true) {
                Future<V> future = cache.get(arg);  //得到一个Future<V>,Future<V>如果不为空,则包含要查找的值
    
                if (future == null) {  //如果future为空。也就是缓存中没有。
                    Callable<V> eval=()->{   //创建一个Callable,调用接口中的计算方法compute,
                        return c.compute(arg); //有可能涉及长时间计算
    }; FutureTask<V> futureTask = new FutureTask<V>(eval); //将callable传递给futureTask; future = cache.putIfAbsent(arg, futureTask); //判断arg是否在cache中存在,如果不存在,把计算任务委托给futureTask。这时futureTask还不执行,需要调用下面的run()之后才执行。 // 不过如果有新的线程进入调用取arg的值时,就不能添加了,因为arg已经存在了,只是值还不存在,要等到下面计算完成后,取出结果就行了。 if (future == null) { //如果future为空。 future=futureTask; // 将futureTask赋给future futureTask.run(); //调用eval 中的call方法,相当于调用compute  } } try { return future.get(); //最后通过future.get()得到想要的值V } catch (Exception e) { } } } }

    3:编写测试类

    package chapter05.class6;
    
    public class MemoizerTest {
    
        public static void main(String[] args){
            Memoizer memoizer = new Memoizer<Integer,String>((s)->{  //compute方法,被c.compute(arg);调用
                return Integer.parseInt(s)+1;
            });
    
            try {
                Integer compute = (Integer) memoizer.compute("23");
                System.out.println(compute);  //24
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
  • 相关阅读:
    postman自动化测试断言
    sqlserver 数据库查询 数据库连接情况和 什么语句造成死锁
    asp.net core 中async/await
    2019年4月15日 查询功能1
    2019年3月21日 装饰器进阶2-带参数的装饰器
    2019年3月10日 装饰器进阶-模拟session
    2019年3月9日 解压序列
    2019年2月24日 装饰器基本实现
    2019年2月23日 装饰器1:高阶函数,函数嵌套
    2019年2月3日 装饰器,小年夜
  • 原文地址:https://www.cnblogs.com/liyafei/p/8716058.html
Copyright © 2011-2022 走看看