toolskit:
FutureTask、ConcurrentMap、concurrentHashMap
public class ****Memory<A,V> implement xxxx<A,V>{
private final ConcurrentMap<A,FutureTask<V>> cache =
new ConcurrentHashMap<A,FutureTask<V>>();
private final xxxx c;
public ****Memory<A,V>(xxxx<A,V> c){
this.c = c;
}
public V execute(final A arg)throws InterruptedException{
while(true){
Future<V> f = cache.get(arg);
if(f==null){
Callable<V> cal = new Callable<V>(){
@Override
public V call() throws Exception {
return c.execute(arg);
}
}
FutureTask<V> ft = new FutureTask<V>(cal);
f = cache.putIfAbsent(arg,ft);
if(f==null){
f = ft;
ft.run;
}
try{
return f.get();
}cach(CancellationExection e){
cache.remove(arg,f);
}catch(ExcutionException e){
throw launderThrowable(e.getCause());
}
}
}
}
}
说明:
一、为什么使用ConcurrentHashMap
高并发,多线程访问,保持数据一致性
二、为什么使用FutureTask
避免重复执行问题。例如当两个线程对arg参数同时判断出缓存中没有相应的值时都会进行一次计算,对复杂计算来说比较消耗性能。使用FutureTask中get操作的阻塞机制,等待另一个线程计算完成直接获取结果。
三、为什么使用putIfAbsent()方法
针对仍有可能多个线程同时对相同的arg判断缓存中没有相应的值,都进行一次耗时计算。put()操作是对ConcurrentHashMap底层的Map对象操作,不具有原子性操作。所以采用ConcurrentHashMap的原子性操作方法putIfAbsent().
四、为什么使用while循环
发生取消计算异常时重新计算