一个cache的改造过程
在分布式的程序中,cache的合理使用可以带来性能上的极大提升,尤其是在资源创建需要昂贵的开销时。cache的设计最重要的是要保证线程安全和高效性。下面以代码为例,介绍了三种cache的写法。
1. 粗放的加锁
public class Cache1 {private HashMap route2SG = null;public Cache1() {route2SG = new HashMap();}public synchronized ServerGroup get(String routeKey) throws IOException {ServerGroup sg = null;sg = route2SG.get(routeKey);if (sg == null) {sg = getServerGroup(routeKey);route2SG.put(routeKey, sg);}return sg;}public synchronized void remove(String routeKey) {route2SG.remove(routeKey);}private ServerGroup getServerGroup(String routeKey) throws IOException {ServerGroup sg = null;/** * Construct ServerGroup here */return sg;}}2. 读写锁
public class Cache2 {private ConcurrentHashMap route2SG = null;private final ReadWriteLock lock = new ReentrantReadWriteLock();public Cache2() {route2SG = new ConcurrentHashMap();}public ServerGroup get(String routeKey) throws IOException {ServerGroup sg = null;try {lock.readLock().lock();sg = route2SG.get(routeKey);if (sg == null) {lock.readLock().unlock();lock.writeLock().lock();sg = route2SG.get(routeKey);if (sg == null) {sg = getServerGroup(routeKey);route2SG.put(routeKey, sg);}lock.readLock().lock();lock.writeLock().unlock();}} catch (IOException e) {lock.writeLock().unlock();throw (e);}lock.readLock().unlock();return sg;}public void remove(String routeKey) {try {lock.writeLock().lock();route2SG.remove(routeKey);} finally {lock.writeLock().unlock();}}private ServerGroup getServerGroup(String routeKey) throws IOException {ServerGroup sg = null;/** * Construct ServerGroup here */return sg;}}3. 无锁
public class Cache3 {private ConcurrentHashMap> route2SGFT = null;public Cache3() {route2SGFT = new ConcurrentHashMap>();}public ServerGroup get(String routeKey) throws IOException, InterruptedException, ExecutionException {FutureTask ft = route2SGFT.get(routeKey);if (ft != null) {return ft.get();}FutureTask sft = new FutureTask(new ConstructSGTask(routeKey));FutureTask old = route2SGFT.putIfAbsent(routeKey, sft);if (old == null) { old=sft;old.run();}return old.get();}public void remove(String routeKey) {route2SGFT.remove(routeKey);}class ConstructSGTask implements Callable {private final String key;public ConstructSGTask(String key) {super();this.key = key;}@Overridepublic ServerGroup call() throws Exception {return getServerGroup(key);}}private ServerGroup getServerGroup(String routeKey) throws IOException {ServerGroup sg = null;/** * Construct ServerGroup here */return sg;}}总结,
从三份代码中可以看出,锁的粒度从粗放到无,这个就极大的提高了cache的并发性。