package com.yw.cache;
import javax.annotation.concurrent.GuardedBy;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author x y
* @description 高效可伸缩的结果缓存
* @date 2022-03-16 11:47
*/
public class CacheMain implements Computable<String, BigInteger> {
@Override
public BigInteger compute(String arg) throws InterruptedException {
// 在进过长时间计算后
return new BigInteger(arg);
}
}
interface Computable<A, V> {
V compute(A arg) throws InterruptedException;
}
class MemoizerOne<A, V> implements Computable<A, V> {
@GuardedBy("this")
private final Map<A, V> cache = new HashMap<>();
private final Computable<A, V> c;
private final ReentrantLock lock = new ReentrantLock();
MemoizerOne(Computable<A, V> computable) {
this.c = computable;
}
@Override
public V compute(A arg) throws InterruptedException {
final ReentrantLock l = this.lock;
l.lock();
try {
V result = cache.get(arg);
if (result == null) {
result = c.compute(arg);
cache.put(arg, result);
}
return result;
} finally {
l.unlock();
}
}
}
class MemoizerTwo<A, V> implements Computable<A, V> {
@GuardedBy("this")
private final Map<A, V> cache = new ConcurrentHashMap<>();
private final Computable<A, V> c;
MemoizerTwo(Computable<A, V> computable) {
this.c = computable;
}
@Override
public V compute(A arg) throws InterruptedException {
V result = cache.get(arg);
if (result == null) {
result = c.compute(arg);
cache.put(arg, result);
}
return result;
}
}
class MemoizerThree<A, V> implements Computable<A, V> {
@GuardedBy("this")
private final Map<A, Future<V>> cache = new ConcurrentHashMap<>();
private final Computable<A, V> c;
MemoizerThree(Computable<A, V> computable) {
this.c = computable;
}
/**
* 检查某个相应的计算已经开始没有,如果还没启动创建一个FutureTask 并注册Map中,然后启动计算;如果启动则等待对应结果即可。
**/
@Override
public V compute(A arg) throws InterruptedException {
Future<V> result = cache.get(arg);
if (result == null) {
Callable<V> callable = new Callable<V>() {
@Override
public V call() throws Exception {
return c.compute(arg);
}
};
FutureTask task = new FutureTask(callable);
result = task;
cache.put(arg, result);
task.run(); // 在这里调用c.compute(arg)
}
try {
return result.get();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
}
}
class MemoizerFour<A, V> implements Computable<A, V> {
@GuardedBy("this")
private final Map<A, Future<V>> cache = new ConcurrentHashMap<>();
private final Computable<A, V> c;
MemoizerFour(Computable<A, V> computable) {
this.c = computable;
}
/**
* 检查某个相应的计算已经开始没有,如果还没启动创建一个FutureTask 并注册Map中,然后启动计算;如果启动则等待对应结果即可。
* 解决if判断中非原子的先检查在执行操作,所以两个线程仍然有机会同一时间调用compute计算相同值,即两者都没找到期望的值,因此都开始计算。
**/
@Override
public V compute(A arg) throws InterruptedException {
for (; ; ) { // 为什么不用while(true)因为for会被虚拟机直接优化为死循环,而while(true)还需要运行判断
Future<V> result = cache.get(arg);
if (result == null) {
Callable<V> callable = new Callable<V>() {
@Override
public V call() throws Exception {
return c.compute(arg);
}
};
FutureTask task = new FutureTask(callable);
result = cache.putIfAbsent(arg, result);
if (result == null) {
result = task;
task.run();// 在这里调用c.compute(arg)}
}
try {
return result.get();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
}
}
}
}
高效可伸缩的结果缓存
最新推荐文章于 2023-06-20 14:04:42 发布