-------
android培训、
java培训、期待与您交流! ----------
public class CachedDemo {
/**
* 缓存系统
* 既然是存的缓存系统里面存储的就不是一个对象
* 就是别人想要获取某个对象的时候,可以通过我们的缓存系统去进行查找
* 我们先查找当前的缓存系统中是否有这个对象
* 如果有就返回该对象。如果没有就查找数据库
*/
//把对象存储在map集合中
private Map<String,Object> map=new HashMap<String,Object>();
public static void main(String[] args) {
}
//现在我们来使用读写锁来改写代码
private ReadWriteLock rwl=new ReentrantReadWriteLock();
public synchronized Object getData(String key){ //别人是通过key来获取对象
//一上来就上读锁
rwl.readLock().lock(); //上读锁所有的线程都是可以读的。所以线程都可以到这里来
Object obj=null; //局部变量在使用的时候一定要先初始化
try {
obj = map.get(key);
if (obj == null) {
//如果有一个线程发现数据为空了的话。就把读锁释放掉。要填充数据
rwl.readLock().unlock();
//上写锁开始写数据
rwl.writeLock().lock(); //这样其它的线程都被堵在外面了
try{
if(obj==null){
obj = "query db"; //实际上是我们在这里就要去数据库中进行查找了
}
}catch(Exception e){
e.printStackTrace();
}finally{
//数据填充完之后把写锁给释放掉
rwl.writeLock().unlock();
//把读锁恢复
rwl.readLock().lock();
}
}
} catch (Exception e) {
// TODO: handle exception
}finally{
rwl.readLock().unlock(); //全部读完之后把读锁给释放掉
}
return obj; //这样下次再来查找的时候,如果数据是存在的就不用再查找数据库而是直接返回该数据了
}
//要让多个线程访问的时候产生互斥要使用synchronized将这个方法进行互斥
/* 我们在上面的时候发现了一个问题,如果有三个线程,它们都进来了。第一个线程发现数据为空,把锁给释放掉了
其它的线程把就把锁都给释放掉了。然后它上了写锁,这样其它的线程是堵在外面的,它在填充完数据之后,把写锁给
释放掉了,然后恢复了读锁的状态。第一个线程执行完之后,第二个线程,他也判断数据为空,它也进来了。它把读锁给释放掉了
然后也也了写锁,然后给对象重复的赋值了。所以我们为了避免这类情况的发生。在对象填充数据的语句外面再进行一次判断。
即线程是在上了写锁之后,如果数据为空的时候,才填充数据。不为空则不填充。
这项是来自于:
class CachedData {
Object data;
volatile boolean cacheValid;
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
void processCachedData() {
rwl.readLock().lock();
if (!cacheValid) {
// Must release read lock before acquiring write lock
rwl.readLock().unlock();
rwl.writeLock().lock();
// Recheck state because another thread might have acquired
// write lock and changed state before we did.
if (!cacheValid) {
data = ...
cacheValid = true;
}
// Downgrade by acquiring read lock before releasing write lock
rwl.readLock().lock();
rwl.writeLock().unlock(); // Unlock write, still hold read
}
use(data);
rwl.readLock().unlock();
}
}*/
}