改自《Java Concurrency in Practice》Listing 5.19. Final Implementation of Memoizer.
比我之前自己写的好多了,必备工具类,记下来留着以后常用
特点:
1.使用Future与ConcurrentMap#putIfAbsent(K key, V value)避免了多个线程重复计算
2.如果计算被取消或失败,会调用ConcurrentMap#remove(key, future)来避免Cache Pollution
使用举例:
比我之前自己写的好多了,必备工具类,记下来留着以后常用
特点:
1.使用Future与ConcurrentMap#putIfAbsent(K key, V value)避免了多个线程重复计算
2.如果计算被取消或失败,会调用ConcurrentMap#remove(key, future)来避免Cache Pollution
- public interface Computable<K, V> {
- V compute(final K key) throws InterruptedException;
- }
- public class ConcurrentCache<K, V> implements Computable<K, V> {
- private static final int DEFAULT_INITIAL_CAPACITY = 16;
- private static final int DEFAULT_CONCURRENCY_LEVEL = 16;
- private static final float DEFAULT_LOAD_FACTOR = 0.75f;
- private final ConcurrentMap<K, Future<V>> cache;
- private final Computable<K, V> computable;
- public ConcurrentCache(Computable<K, V> computable) {
- this(computable, DEFAULT_INITIAL_CAPACITY, DEFAULT_CONCURRENCY_LEVEL);
- }
- public ConcurrentCache(Computable<K, V> computable, int initialCapacity, int concurrencyLevel) {
- this(computable, initialCapacity, DEFAULT_LOAD_FACTOR, concurrencyLevel);
- }
- public ConcurrentCache(Computable<K, V> computable, int initialCapacity, float loadFactor, int concurrencyLevel) {
- this.computable = computable;
- cache = new ConcurrentHashMap<K, Future<V>>(initialCapacity, loadFactor, concurrencyLevel);
- }
- @Override
- public V compute(final K key) throws InterruptedException {
- while (true) {
- Future<V> future = cache.get(key);
- if (future == null) {
- FutureTask<V> futureTask = new FutureTask<V>(new Callable<V>() {
- @Override
- public V call() throws Exception {
- return computable.compute(key);
- }
- });
- /**
- * V putIfAbsent(K key, V value)
- * 等效于以下代码,只不过以原子操作的方式执行
- * if (!map.containsKey(key))
- * return map.put(key, value);
- * else
- * return map.get(key);
- */
- future = cache.putIfAbsent(key, futureTask);
- if (future == null) {
- future = futureTask;
- futureTask.run();
- }
- }
- try {
- return future.get();
- } catch (InterruptedException e) {
- /**
- * boolean remove(Object key, Object value)
- * 等效于以下代码,只不过以原子操作的方式执行
- * if (map.containsKey(key) && map.get(key).equals(value)) {
- * map.remove(key);
- * return true;
- * } else {
- * return false;
- * }
- */
- cache.remove(key, future);
- throw e;
- } catch (CancellationException e) {
- cache.remove(key, future);
- } catch (ExecutionException e) {
- cache.remove(key, future);
- throw new RuntimeException(e.getCause());
- } catch (RuntimeException e) {
- cache.remove(key, future);
- throw e;
- }
- }
- }
- }
使用举例:
- static final ConcurrentCache<Class<?>, Map<String, FieldInfo>> FIELDINFO_GETTERS_CACHE =
- new ConcurrentCache<Class<?>, Map<String, FieldInfo>>(
- new Computable<Class<?>, Map<String, FieldInfo>>() {
- @Override
- public Map<String, FieldInfo> compute(Class<?> clazz) throws InterruptedException {
- Map<String, FieldInfo> fieldInfoMap = new HashMap<String, FieldInfo>();
- // 省略...
- return fieldInfoMap;
- }
- });
- public static Map<String, FieldInfo> computeGetters(final Class<? extends Event> clazz) {
- return FIELDINFO_GETTERS_CACHE.compute(clazz);
- }