多线程、高性能缓存服务实现代码

来源:互联网 发布:化妆品数据分析 编辑:程序博客网 时间:2024/06/06 09:09

1、接口定义

import java.util.concurrent.ExecutionException;

public interface Computable<A,V> {
V compute(A arg) throws InterruptedException, ExecutionException;
}

2、类实现

import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

public class Memoizer<A, V> implements Computable<A, V> {

private final ConcurrentHashMap<A, Future<V>> cache = new ConcurrentHashMap<A, Future<V>>(); // 线程安全类
private final Computable<A, V> c; // private,final关键词可以尽量的使用

public Memoizer(Computable<A, V> c) {
this.c = c;
}

public V compute(final A arg) throws InterruptedException, ExecutionException {
while(true){
Future<V> f = cache.get(arg);
if(f==null){
Callable<V> eval = new Callable<V>() {
public V call() throws Exception {
return c.compute(arg);
}
};
FutureTask<V> ft = new FutureTask<V>(eval);
f = cache.putIfAbsent(arg, ft); // 缺失即添加的原子化操作
if(f==null){
f = ft;
ft.run(); // 开始计算结果
}
}
try {
return f.get();
} catch (CancellationException e) {
cache.remove(arg, f); // 避免污染数据添加到缓存
} catch (ExecutionException e0) {
throw e0;
}
}
}
}

3、在servlet中调用

import java.io.IOException;
import java.util.concurrent.ExecutionException;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;


public class Factorizer extends HttpServlet {

private final Computable<Integer, Integer[]> c = new Computable<Integer, Integer[]>() {
public Integer[] compute(Integer arg) throws InterruptedException, ExecutionException {
return new Integer[arg.intValue()];
}
};
private final Computable<Integer, Integer[]> cache = new Memoizer<Integer, Integer[]>(c);

// 主方法,多线程共享变量就是线程安全的cache
public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException {
try {
Integer i = extractFromRequest(req);
encodeIntoResponse(resp, cache.compute(i));
} catch (Exception e) {
// TODO: handle exception
}
}

// 以下两个方法是辅助方法
private void encodeIntoResponse(ServletResponse resp, Integer[] compute) {
try {
resp.getWriter().write(compute[0]);
} catch (IOException e) {
e.printStackTrace();
}
}

private Integer extractFromRequest(ServletRequest req) {
return Integer.valueOf(100);
}

}



原创粉丝点击