多线程操作----缓存

private Map<String,String> cache = new HashMap<String,String>();//这里只是一个普通的map,所以需要读写锁来保证原子性,而java并发库已经帮助我们做到了这一点
private ReadWriteLock rwl = new ReentrantReadWriteLock();
	public  Object getData(String key){
		rwl.readLock().lock();
		
		Object value = null;
		try{
			value = cache.get(key);
			if(value == null){ //如果没读到,释放读锁,加写锁
				rwl.readLock().unlock();
				
				rwl.writeLock().lock();
				try{
					value = cache.get(key);
					if(value==null){ // 防止重复写,只有value为空的时候才能写,
						//比如有两个线程到了rwl.writeLock().lock();,第一个线程先拿到写锁,写完后,第二个线程就不应该去写了,所以这里对第二个线程要验证下
						value = "aaaa";//实际失去queryDB();//这个地方可能需要很长时间,这里是把计算完后的结果传给cache,后面把这里改进了
						cache.put(key, value);
					}
				}finally{
					rwl.writeLock().unlock();
				}
				rwl.readLock().lock();
			}
		}finally{
			rwl.readLock().unlock();
		}
		return value;
	}


高性能的cache
interface Computable<A,V>{
	V compute(A arg) throws InterruptedException;
}
class Memoizer<A,V> implements Computable<A,V>{
	//A代表输入,Future<V>代表输出的结果
	private final ConcurrentMap<A, Future<V>> cache=new ConcurrentHashMap<A, Future<V>>();
	//使用Future的好处是,如果有某个线程已经开始在做这件事情,但是还没拿到结果,那么其他线程就不会去重复做这件事情了,只需要等待那个线程的结果即可
	
	//private final ConcurrentMap<A, V> cache2=new ConcurrentHashMap<A, V>(); 
	private final Computable<A,V> c;
	public Memoizer(Computable<A,V> c){
		this.c=c;
	}
	@Override
	public V compute(final A arg) throws InterruptedException {
		while(true){
			Future<V> f= cache.get(arg); //判断计算是否已经开始  ,区别于cache2,他判断的是一个结果是否已经完成
			if(f == null){//如果计算还未开始
				//定制一个任务
				Callable<V> eval = new Callable<V>() {
					@Override
					public V call() throws Exception {
						// TODO Auto-generated method stub
						return c.compute(arg);
					}
				};
				FutureTask<V> ft = new FutureTask<V>(eval);//FutureTask就是一线程,可以run Callable的线程
				
				//注册到map中
				f= cache.putIfAbsent(arg, ft);
				if(f==null){//再次判断,防止两个线程重复做同样的事情
					f=ft;
					ft.run();
				}
			}
			try{
				return f.get();//其他线程在计算结果,所以此线程本事就不需要去拿结果了,只需要等待其他线程返回结果即可
			}catch (CancellationException e) {
				cache.remove(arg,f);
			}catch(Exception e){
				
			}
		}
	}

你可能感兴趣的:(多线程)