package concurrency.synchronizer;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
interface Compute {
public Integer compute(Integer key);
}
/**
* 对于一个较大运算量的缓存来说,这样的效果是远远不够的,因为对于同一个值,会计算两次,
* 因此,我们想要的就是让后来的线程知道它请求的值正在计算当中,等待计算结束后直接返回计算后
* 的值就可以了,没有必要再进行一次计算
* 因此了后第二个改进的版本
* @author Administrator
*
*/
public class Cache {
private static final Map<Integer, Integer> CACHE = new ConcurrentHashMap<Integer, Integer>();
private static final Compute COMP = new Compute() {
@Override
public Integer compute(Integer key) {
System.out.println(Thread.currentThread().getName()+"start compute");
Integer result = 1;
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(100 * 1);
} catch (InterruptedException e) {
e.printStackTrace();
}
result *= key;
}
return result;
}
};
public static Integer getCache(Integer key) {
Integer retVal = CACHE.get(key);
if (retVal == null) {
retVal = COMP.compute(key);
CACHE.put(key, retVal);
}
return retVal;
}
private static final Cache INSTANCE = new Cache();
private static final Cache getInstance() {
return INSTANCE;
}
public static void main(String args[]) throws InterruptedException {
final Cache cache = Cache.getInstance();
Thread t1 = new Thread("t1"){
@Override
public void run() {
Integer key = 10;
System.out.println(Thread.currentThread().getName()+" get value from cache "+cache.getCache(key));
}
};
Thread t2 = new Thread("t2"){
@Override
public void run() {
Integer key = 10;
System.out.println(Thread.currentThread().getName()+" get value from cache "+cache.getCache(key));
}
};
t1.start();
t2.start();
}
}
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
package concurrency.synchronizer;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Cache2 {
private static final ConcurrentMap<Integer, FutureTask<Integer>> CACHE = new ConcurrentHashMap<Integer, FutureTask<Integer>>();
private static final Compute COMP = new Compute() {
@Override
public Integer compute(Integer key) {
System.out.println(Thread.currentThread().getName()+"start compute");
Integer result = 1;
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(100 * 1);
} catch (InterruptedException e) {
e.printStackTrace();
}
result *= key;
}
return result;
}
};
public static Integer getCache(final Integer key) throws InterruptedException{
FutureTask<Integer> task = CACHE.get(key);
if(task ==null){
task = new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return COMP.compute(key);
}
}){};
FutureTask<Integer> preTask = CACHE.putIfAbsent(key, task);
if(preTask == null){ // 说明被加进去了
task.run();
}else{
task = preTask;
}
}
try {
return task.get();
} catch (CancellationException e) {
CACHE.remove(key);
return null;
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
private Cache2() {
}
public static final Cache2 INSTANCE = new Cache2();
private static Cache2 getInstance() {
return INSTANCE;
}
public static void main(String args[]) {
final Cache2 cache = Cache2.getInstance();
Thread t1 = new Thread(){
@Override
public void run() {
Integer key = 10;
try {
System.out.println(Thread.currentThread().getName()+cache.getCache(key));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Thread t2 = new Thread(){
@Override
public void run() {
Integer key = 10;
try {
System.out.println(Thread.currentThread().getName()+cache.getCache(key));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
t1.start();
t2.start();
}
}