支持并发的结果缓存

来源:互联网 发布:淘宝网阿里巴巴找密码 编辑:程序博客网 时间:2024/05/19 16:34
改自《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. }  



使用举例: 
Java代码  收藏代码
  1. static final ConcurrentCache<Class<?>, Map<String, FieldInfo>> FIELDINFO_GETTERS_CACHE =  
  2. new ConcurrentCache<Class<?>, Map<String, FieldInfo>>(  
  3.             new Computable<Class<?>, Map<String, FieldInfo>>() {  
  4.   
  5.                 @Override  
  6.                 public Map<String, FieldInfo> compute(Class<?> clazz) throws InterruptedException {  
  7.                     Map<String, FieldInfo> fieldInfoMap = new HashMap<String, FieldInfo>();  
  8.                     // 省略...  
  9.                     return fieldInfoMap;  
  10.                 }  
  11.             });  
  12.   
  13.   
  14. public static Map<String, FieldInfo> computeGetters(final Class<? extends Event> clazz) {  
  15.         return FIELDINFO_GETTERS_CACHE.compute(clazz);  
  16. }  
0 0
原创粉丝点击