Created
February 26, 2014 02:43
-
-
Save snowdream/9222531 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.concurrent.Callable; | |
import java.util.concurrent.ConcurrentHashMap; | |
import java.util.concurrent.ExecutionException; | |
import java.util.concurrent.Future; | |
import java.util.concurrent.FutureTask; | |
interface Computable<K,V>{ | |
V compute(final K arg); | |
} | |
/** | |
* 实现简单缓存系统 | |
* @author mzy | |
* | |
* @param <K> key | |
* @param <V> value | |
*/ | |
public class FutureCache<K,V> implements Computable<K,V>{ | |
private final ConcurrentHashMap<K, Future<V>> cache = new ConcurrentHashMap<K ,Future<V>>(); | |
private final Computable<K, V> c; | |
public FutureCache(Computable<K, V> c) { | |
this.c = c; | |
} | |
@Override | |
public V compute(final K key) { | |
while(true){ | |
Future<V> future = cache.get(key); | |
if(future == null){ | |
Callable<V> eval = new Callable<V>() { | |
@Override | |
public V call() throws Exception { return c.compute(key); } | |
}; | |
FutureTask<V> ftask = new FutureTask<V>(eval); | |
//使用putIfAbsent原子操作避免有上面if(future == null)引起的相同值的缺陷 | |
future = cache.putIfAbsent(key, ftask); | |
if(future == null) { future = ftask; ftask.run(); } | |
} | |
try { | |
return future.get(); | |
} catch (InterruptedException e) { | |
//出现中断异常应该从 cache中移除Future,防止缓存污染 | |
cache.remove(key,future); | |
} catch (ExecutionException e) { | |
//执行中的异常应当抛出,获得恰当处理 | |
throw new RuntimeException(e.getCause()); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment