自定义计算缓存的实现

package org.whf.cache;

/**
 * Created by hongfei.whf on 2016/10/3.
 */
public interface Computable<INPUT, OUTPUT> {

    /**
     * 通过参数key得到结果value的计算过程
     *
     * @param input
     * @return
     */
    public OUTPUT compute(INPUT input) throws CalculationException;
}
package org.whf.cache.org.whf.cache.impl;

import org.whf.cache.CalculationException;
import org.whf.cache.Computable;

import java.util.concurrent.*;

/**
 * Created by hongfei.whf on 2016/10/3.
 */
public class Memoizer<INPUT, OUTPUT> implements Computable<INPUT, OUTPUT> {

    /**
     * 缓存并发容器:
     * 优势->避免访问串行化和并发造成的key的相同重复计算,以及一系列复合原子操作简化编程
     */
    private final ConcurrentHashMap<INPUT, FutureTask<OUTPUT>> cache = new ConcurrentHashMap<>();

    /**
     * 实际进行的计算过程
     */
    private Computable<INPUT, OUTPUT> calc = null;

    /**
     * 构造函数
     *
     * @param calc
     */
    public Memoizer(Computable<INPUT, OUTPUT> calc) {
        this.calc = calc;
    }

    /**
     * compute 通过参数key进行一系列的计算后得到的value,并且对该结果进行缓存,
     * 下次访问直接获取缓存中的结果,如果另有线程正在计算,
     * 可以阻塞当前线程等待结果并且返回,避免重复计算
     *
     * @param input
     * @return
     */
    @Override
    public OUTPUT compute(INPUT input) throws CalculationException {
        while (true) {
            FutureTask<OUTPUT> currTask = null;
            if (!cache.containsKey(input) || (currTask = cache.get(input)) == null) {
                FutureTask<OUTPUT> task = new FutureTask<OUTPUT>(new Callable<OUTPUT>() {
                    @Override
                    public OUTPUT call() throws Exception {
                        return calc.compute(input);
                    }
                });
                currTask = cache.putIfAbsent(input, task);
                if (currTask == null) {
                    currTask = task;
                    currTask.run();
                }
            }
            // 避免缓存污染,计算过程被取消或者出现异常失败
            try {
                return currTask.get();
            } catch (InterruptedException e) {
                // 计算被取消,删除缓存中的内容重新计算
                cache.remove(input);
                e.printStackTrace();
            } catch (ExecutionException e) {
                // 计算过程中出现失败或者失败,直接抛出异常
                e.printStackTrace();
                throw new CalculationException(e);
            } catch (CancellationException e) {
                // 计算被取消,删除缓存中的内容重新计算
                cache.remove(input);
                e.printStackTrace();
            }
        }
    }

}
import org.whf.cache.CalculationException;
import org.whf.cache.Computable;
import org.whf.cache.org.whf.cache.impl.Memoizer;

import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Main {

    public static void main(String[] args) throws IOException, InterruptedException, CalculationException, ExecutionException {
        Memoizer<Integer, Integer> memoizer = new Memoizer<>(new Computable<Integer, Integer>() {
            @Override
            public Integer compute(Integer input) {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return input / 1;
            }
        });
        System.out.println(memoizer.compute(10));
        System.out.println(memoizer.compute(10));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值