问题描述:
计算输入的数是否是素数是一个耗时的过程,我们现在用cache来存储计算过的值,方便下次检索使用。
cache的两种实现模式:
- Double Check 实现;
- FutureTask 实现;
先看计算是否是素数的代码:
package test.concurrency;
import java.util.concurrent.TimeUnit;
public class PrimeUtil {
public static boolean isPrime(long num){
try {
// 故意睡会儿,表示这个计算很耗时
TimeUnit.MILLISECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(num == 1){
return false;
}else if(num == 2){
return true;
}else{
for(int n = 2; n<=Math.sqrt(num); n++){
if(num%n == 0){
return false;
}
}
return true;
}
}
}
Double Check 版cache的实现:
package test.concurrency;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class PrimeDoubleCheckCache {
private ConcurrentMap<Long, Boolean> primes;
private Lock lock = new ReentrantLock();
public PrimeDoubleCheckCache(int size){
primes = new ConcurrentHashMap<>(size*3/2);
}
public boolean isPrime(long num){
Boolean r = primes.get(num);
if(r == null){
try{
lock.lock();
if(r == null){
r = PrimeUtil.isPrime(num);
}
}finally{
lock.unlock();
}
primes.putIfAbsent(num, r);
}
return r;
}
}
FutureTask 版cache的实现:
package test.concurrency;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
public class PrimeFutureCache {
private ConcurrentMap<Long, Future<Boolean>> primes;
public PrimeFutureCache(int size){
primes = new ConcurrentHashMap<>(size*3/2);
}
public boolean isPrime(long num){
while(true){
try{
Future<Boolean> f = primes.get(num);
if(f == null){
FutureTask<Boolean> task = new FutureTask<>(new Callable<Boolean>(){
@Override
public Boolean call() throws Exception {
return PrimeUtil.isPrime(num);
}
});
Future<Boolean> f1 = primes.putIfAbsent(num, task);
if(f1 == null){
task.run();
f = task;
}else{