支持并发的结果缓存

改自《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. }  
public interface Computable<K, V> {
	V compute(final K key) throws InterruptedException;
}


 

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. }  
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;
			}
		}
	}
}



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值