//计算 public interface Computable<A, V> { V compute(A arg) throws InterruptedException; } /** 第一种最简单实现:采用HashMap,直接在compute()方法上加锁这种构建缓存的方式有很大问题, * 如果compute执行时间很长那么有很多线程都要排队等待,那么此时效率可能比没有缓存还低.*/ public class Momizer1<A, V> implements Computable<A, V>{ private final Map<A, V> cacheMap = new HashMap<A, V>(); private final Computable<A, V> computable; public Momizer1(Computable<A, V> computable){ this.computable = computable; } @Override public synchronized V compute(A arg) throws InterruptedException { V v = cacheMap.get(arg); if(v==null){ v = computable.compute(arg); cacheMap.put(arg, v); } return v; } } /** 第二种实现:用ConcurrentHashMap代替HashMap,由于ConcurrentHashMap是线程安全的且效率比较高,所以比第一种效率高. * 但是这种方式会产生重复计算问题,假如传入相同的值,因为线程间不知道是否已经开始计算,所以都会去计算。*/ public class Momizer2<A, V> implements Computable<A, V>{ private final ConcurrentHashMap<A, V> cacheMap = new ConcurrentHashMap<A, V>(); private final Computable<A, V> computable; public Momizer2(Computable<A, V> computable){ this.computable = computable; } @Override public V compute(A arg) throws InterruptedException { V v = cacheMap.get(arg); if(v==null){ v = computable.compute(arg); cacheMap.put(arg, v); } return v; } } /** 第三种实现:将长时间的计算过程用FutureTask替代,如果FutureTask计算结果完毕,那么直接返回结果, * 如果没有那么久阻塞等待返回结果.但是这种方式还是没有解决重复计算问题,虽然概率远小于第二种方式.因为 * 存在符合操作若没有则添加*/ public class Momizer3<A, V> implements Computable<A, V>{ private final ConcurrentHashMap<A, FutureTask<V>> cacheMap = new ConcurrentHashMap<A, FutureTask<V>>(); private final Computable<A, V> computable; public Momizer3(Computable<A, V> computable){ this.computable = computable; } @Override public V compute(final A arg) throws InterruptedException { FutureTask<V> futureTask = cacheMap.get(arg); // if(futureTask==null){ Callable<V> callable = new Callable<V>() { @Override public V call() throws Exception { return computable.compute(arg); } }; FutureTask<V> f = new FutureTask<>(callable); futureTask = f; cacheMap.put(arg, f); f.run(); /*futureTask = new FutureTask<>(callable); cacheMap.put(arg, futureTask); futureTask.run();*/ } try { return futureTask.get(); } catch (ExecutionException e) { throw new RuntimeException(); } } } /** * 第四种实现:利用ConcurrentHashMap的putIfAbsent方法实现,这个方法相当于如果有就返回值,没有就返回null并讲值放入map. */ public class Momizer4<A, V> implements Computable<A, V> { private final ConcurrentHashMap<A, FutureTask<V>> cacheMap = new ConcurrentHashMap<A, FutureTask<V>>(); private final Computable<A, V> computable; public Momizer4(Computable<A, V> computable) { this.computable = computable; } @Override public V compute(final A arg) throws InterruptedException { while(true){ FutureTask<V> f = cacheMap.get(arg); if(f==null){ Callable<V> callable = new Callable<V>() { @Override public V call() throws Exception { return computable.compute(arg); } }; FutureTask<V> ft = new FutureTask<>(callable); f = cacheMap.putIfAbsent(arg, ft); if(f==null){f=ft;ft.run();} } try { return f.get(); } catch (CancellationException e) { //如果FutureTask调用了取消那么清除缓存重新循环放入 cacheMap.remove(arg); }catch (ExecutionException e) { e.printStackTrace(); } } } }
一个简单的学习多线程缓存的demo
一个简单的学习多线程缓存的demo:
猜你喜欢
转载自chen-sai-201607223902.iteye.com/blog/2373627
今日推荐
周排行