Java 读写锁的应用 自定义的缓存系统

来源:互联网 发布:白熊事务所装软件 编辑:程序博客网 时间:2024/06/16 08:10
熟悉Hibernate的童鞋  一定知晓Hibernate有一级缓存跟二级缓存 一级缓存是Hibernate默认开启的缓存 而二级缓存需要自己配置 此处只简单的讨论一个
Hibernate中load的内部实现原理
如果你要根据用户id获取用户的信息
User user = session.load(id,User.class);
此处返回的user类型是一个代理对象User$Proxy 而User$Proxy
User$Proxy extends User{
//代理对象持有用户id
private Integer id ;
private User realUuser;
public String getName(){
//首先会查询缓存 如果缓存中有数据则直接返回
    //如果缓存为空 则需要向数据查询 数据 
    //如果从数据中也没有获取到数据 则抛出异常
}
}
故使用session.load方法时 如果没有查询到数据 会抛出异常 此处肯定有一些童鞋很好奇缓存机制是怎么实现的呢?
缓存系统会用读写锁 下面简单的介绍一个简单的缓存系统  实现原理
缓存肯定是多个线程并发访问的 故对效率要求极高 否则你的系统无法承受高并发访问..
大家了解一下读锁与写锁的一些关系
1.读锁与读锁不互斥
       2.读锁与写锁互斥
       3.写锁与写锁互斥
读写锁的妙用 一个简单的缓存系统
/** *  * 一个简单的缓存系统 */class Cache{//数据private Object data;//读写锁ReadWriteLock rwl = new ReentrantReadWriteLock();//获取数据 public Object get(){//用户读取数据  开启读锁System.out.println(Thread.currentThread().getName()+"开始获取数据等待中.");rwl.readLock().lock();System.out.println(Thread.currentThread().getName()+"获取读锁 开始读取数据...");/** *  当查询数据的过程中 出现异常 则不会执行下面的代码  而此时已经获取到读锁了 *  一旦发生异常  锁资源不能释放  故此处用try catch finally 保证资源得到释放 */        try {    if ( data == null ) {    //由于无数据  需要向数据库查询 故要释放读锁    //开启写锁?因为要给data复制 故要开启写锁    System.out.println("数据为空:"+Thread.currentThread().getName()+":..");    rwl.readLock().unlock();    System.out.println(Thread.currentThread().getName()+" 释放读锁");    rwl.writeLock().lock();    //从数据中获取...    System.out.println(Thread.currentThread().getName()+" 获取写锁"); /*** 此处如果不判断数据是否为空 会出现什么情况呢?* 试想一下如果当三个线程同时访问该方法的时候.只有第一个线程可以获取写锁 * 其它线程处于等待...  当该线程写完数据之后 释放写锁* 第二个线程获得写锁  但是此时数据不再为空[第一个获取写锁的线程已经写入数据]* 如果此处不判断数据是否为空 第二个线程会再次查询数据并写入。* 如果是N个线程 同时访问该方法  则会查询N次数据并写入 效率可想而知!* 故为了提高效率 此处再次判断数据是否为空
* 有兴趣的童鞋可以把此处的判断去掉  你看看会发现什么?*/if ( data == null ) {System.out.println(Thread.currentThread().getName()+"开始写入数据");//此处的数据应该是从DB中获取data = "data from db";System.out.println(Thread.currentThread().getName()+"数据写入完毕...");}
//释放写锁  获取读锁/*** 如果是第二个线程获取到写锁之后  经过判断之后 数据不为空 * 则立即释放写锁  再次获取读锁* 至于先释放那个锁  再获取那个锁的顺序 *【如果此处是我自己 我可能会先释放写锁 * rwl.writeLock().unlock();* 在获取读锁* rwl.readLock().lock();】* 此处是模仿JDK文档中关于缓存释放和获取锁的顺序...*/rwl.readLock().lock();rwl.writeLock().unlock();}   } catch (Exception e) {//异常处理   } finally {rwl.readLock().unlock();   }   return data;}}
测试代码:
public static void main(String[] args) {final Cache cache = new Cache();for(int i = 0;i<3;i++){new Thread(){public void run() {Object data = cache.get();System.out.println(Thread.currentThread().getName()+"得到数据"+data.toString());};}.start();}}