为计算结果建立高效、可伸缩的高速缓存

                      为计算结果建立高效、可伸缩的高速缓存
 

复用已有的计算结果可以缩短等待时间,提高吞吐量,代价是占用更多的内存。
Memoizer利用ConcurrentMap中原子化的putIfAbsent方法,缓存一个Future而不是一个值,带来了缓存污染的可能性:如果一个计算被取消或者,失败,未来尝试对这个值进行计算都会表现为取消或者失败。为了避免这个结果,Memoizer如果发现计算被取消,就会把Future从缓存中移除;如果发现有RuntimeException,也会移除Future,这样新请求中的计算才有可能成功。Memoizer同样有缓存过期的问题,但是这些可以通过FutureTask的一个子类来完成,它会为每一个结果关联一个过期时间,并且周期性地扫描缓存中过期的访问。例子是把servlet因式分解的结果缓存起来。
 

public interface Computale<A,V> {
    V compute(A arg) throws InterruptedException;
}
public class Memoizer<A,V> implements Computable<A,V> {
  private final ConcurrentMap<A, Future<V>> cache = 
      new ConcurrentHashMap<A, Future<V>>();
  private final Computable<A,V> c;
  public  Memoizer (Computable<A,V> c) { this.c = c;}
  public V compute(final A arg) throws InterruptedException {
       while (true) {
    Future<V> f = cache.get(arg);
          if(f == null) {
              Callable<V> eval = new Callable<V>() {
                   public V call() throws InterruptedException {
                           return c.compute(arg); 
                   }              
              };
                FutureTask<V> ft = new FutureTask<V>(eval);
                f  = cache.putIfAbsent(arg, ft);
                if (f == null) {f = ft; ft.run();}   //执行compute方法
          }
           try {
                  return f.get();
   }catch (CancellationException e) {
      cache.remove(arg,f);
   }catch(ExecutionException e) {
     throw launderThrowable(e.getCause());
   }
  }
  }
}
使用Memoizer为因式分解的servlet缓存结果
@ThreadSafe
public clas Factorizer implements Servlet {
 private final Computable<BigInteger, BigInteger[]> c = 
        new Computable<BigInteger, BigInteger[]>() {
       public BigInteger[] compute(BigInteger arg) {
               return factor(arg);
            }
       };
 private final Computable<BigInteger, BigInteger[]> cache =
     new Memoizer<BigInteger, BigInteger[]>(c);
 public void servie(ServletRequest req , ServletResponse resp) {
     try{
        BigInteger i = extractFromRequest(req);
        encodeIntoResponse(resp, cache.compute(i));
     }catch(InterruptedException e) {
          encodeError(resp, "factorization interrupted");
     }
 }

}

猜你喜欢

转载自blog.csdn.net/xiao__jia__jia/article/details/81630228
今日推荐