支持并发的结果缓存

来源:互联网 发布:linux防火墙ip地址配置 编辑:程序博客网 时间:2024/05/19 07:11

改自《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

Java代码 复制代码 收藏代码
  1. public interface Computable<K, V> {   
  2.     V compute(final K key) throws InterruptedException;   
  3. }  


 

Java代码 复制代码 收藏代码
  1. public class ConcurrentCache<K, V> implements Computable<K, V> {   
  2.   
  3.     private static final int DEFAULT_INITIAL_CAPACITY = 16;   
  4.     private static final int DEFAULT_CONCURRENCY_LEVEL = 16;   
  5.     private static final float DEFAULT_LOAD_FACTOR = 0.75f;   
  6.   
  7.     private final ConcurrentMap<K, Future<V>> cache;   
  8.     private final Computable<K, V> computable;   
  9.   
  10.     public ConcurrentCache(Computable<K, V> computable) {   
  11.         this(computable, DEFAULT_INITIAL_CAPACITY, DEFAULT_CONCURRENCY_LEVEL);   
  12.     }   
  13.   
  14.     public ConcurrentCache(Computable<K, V> computable, int initialCapacity, int concurrencyLevel) {   
  15.         this(computable, initialCapacity, DEFAULT_LOAD_FACTOR, concurrencyLevel);   
  16.     }   
  17.   
  18.     public ConcurrentCache(Computable<K, V> computable, int initialCapacity, float loadFactor, int concurrencyLevel) {   
  19.         this.computable = computable;   
  20.         cache = new ConcurrentHashMap<K, Future<V>>(initialCapacity, loadFactor, concurrencyLevel);   
  21.     }   
  22.   
  23.     @Override  
  24.     public V compute(final K key) throws InterruptedException {   
  25.         while (true) {   
  26.             Future<V> future = cache.get(key);   
  27.             if (future == null) {   
  28.                 FutureTask<V> futureTask = new FutureTask<V>(new Callable<V>() {   
  29.   
  30.                     @Override  
  31.                     public V call() throws Exception {   
  32.                         return computable.compute(key);   
  33.                     }   
  34.                 });   
  35.   
  36.                 /**  
  37.                  * V putIfAbsent(K key, V value)  
  38.                  * 等效于以下代码,只不过以原子操作的方式执行  
  39.                  * if (!map.containsKey(key))  
  40.                  *      return map.put(key, value); 
  41.                  * else  
  42.                  *      return map.get(key);  
  43.                  */  
  44.                 future = cache.putIfAbsent(key, futureTask);   
  45.                 if (future == null) {   
  46.                     future = futureTask;   
  47.                     futureTask.run();   
  48.                 }   
  49.             }   
  50.             try {   
  51.                 return future.get();   
  52.             } catch (InterruptedException e) {   
  53.                 /**  
  54.                  * boolean remove(Object key, Object value) 
  55.                  * 等效于以下代码,只不过以原子操作的方式执行  
  56.                  * if (map.containsKey(key) && map.get(key).equals(value)) { 
  57.                  *      map.remove(key);  
  58.                  *      return true;  
  59.                  * } else {  
  60.                  *      return false;  
  61.                  * }  
  62.                  */  
  63.                 cache.remove(key, future);   
  64.                 throw e;   
  65.             } catch (CancellationException e) {   
  66.                 cache.remove(key, future);   
  67.             } catch (ExecutionException e) {   
  68.                 cache.remove(key, future);   
  69.                 throw new RuntimeException(e.getCause());   
  70.             } catch (RuntimeException e) {   
  71.                 cache.remove(key, future);   
  72.                 throw e;   
  73.             }   
  74.         }   
  75.     }   
  76. }  



 

原创粉丝点击