一个cache的改造过程

作者: nick 分类: java 发布时间: 2010-10-24 11:58 ė 6没有评论

在分布式的程序中,cache的合理使用可以带来性能上的极大提升,尤其是在资源创建需要昂贵的开销时。cache的设计最重要的是要保证线程安全和高效性。下面以代码为例,介绍了三种cache的写法。

1. 粗放的加锁

public class Cache1 {
	private HashMap<String, ServerGroup> route2SG = null;

	public Cache1() {
		route2SG = new HashMap<String, ServerGroup>();
	}

	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<String, ServerGroup> route2SG = null;
	private final ReadWriteLock lock = new ReentrantReadWriteLock();

	public Cache2() {
		route2SG = new ConcurrentHashMap<String, ServerGroup>();
	}

	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<String, FutureTask<ServerGroup>> route2SGFT = null;

	public Cache3() {
		route2SGFT = new ConcurrentHashMap<String, FutureTask<ServerGroup>>();
	}

	public ServerGroup get(String routeKey) throws IOException, InterruptedException, ExecutionException {
		FutureTask<ServerGroup> ft = route2SGFT.get(routeKey);
		if (ft != null) {
			return ft.get();
		}
		FutureTask<ServerGroup> sft = new FutureTask<ServerGroup>(new ConstructSGTask(routeKey));
		FutureTask<ServerGroup> 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<ServerGroup> {
		private final String key;

		public ConstructSGTask(String key) {
			super();
			this.key = key;
		}

		@Override
		public ServerGroup call() throws Exception {
			return getServerGroup(key);
		}

	}

	private ServerGroup getServerGroup(String routeKey) throws IOException {
		ServerGroup sg = null;
		/**
		 * Construct ServerGroup here
		 */
		return sg;
	}

}

总结,

从三份代码中可以看出,锁的粒度从粗放到无,这个就极大的提高了cache的并发性。

本文出自 传播、沟通、分享,转载时请注明出处及相应链接。

本文永久链接: https://www.nickdd.cn/?p=1159

发表评论

您的电子邮箱地址不会被公开。

Ɣ回顶部