多线程操作----缓存
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;}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;}@Overridepublic 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>() {@Overridepublic V call() throws Exception {// TODO Auto-generated method stubreturn 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){}}}