一个简单的学习多线程缓存的demo

一个简单的学习多线程缓存的demo:

//计算
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();
}
}

}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值