package com.baidu.unbiz.easymapper.util; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 带有记忆功能的工具类,可以在runtime根据算子{@link Computable}进行计算并且缓存结果,线程安全。类似函数式编程中的记忆特性。 * * @author zhangxu */ public class Memoizer<K, V> { private static Logger LOGGER = LoggerFactory.getLogger(Memoizer.class); /** * 缓存 */ private final ConcurrentHashMap<K, Future<V>> cache = new ConcurrentHashMap<K, Future<V>>(); /** * 获取值 * * @param arg key * * @return 值 */ public V get(K arg) { Future<V> future = cache.get(arg); if (future != null) { try { return future.get(); } catch (Exception e) { cache.remove(arg); } } return null; } /** * 清除 */ public void clear() { cache.clear(); } /** * 清除key */ public void remove(K key) { cache.remove(key); } /** * 计算并获取值 * * @param arg key * @param c 算子 * * @return 值 * * @throws InterruptedException */ public V compute(final K arg, final Computable<K, V> c) throws InterruptedException { Future<V> future = cache.get(arg); if (future == null) { FutureTask<V> futureTask = new FutureTask<V>(new Callable<V>() { @Override public V call() throws Exception { return c.compute(arg); } }); future = cache.putIfAbsent(arg, futureTask); if (future == null) { future = futureTask; futureTask.run(); } } try { return future.get(); } catch (Exception e) { LOGGER.error("Get computed result with error - " + e.getMessage(), e); cache.remove(arg); return null; } } }