直接给出第一版程序,如下:


public class CacheDemo

{

private Map<String,Object> data=new HashMap<String,Object>();

public Object getValue(String key)

{

Object value=data.get(key);

if(value==null)

{//说明缓存中没有数据,那么需要去数据库中获取,然后放入缓存

value="数据库中获取的数据";

data.put(key,vakue);

}

return value;

}

}

上面的版本即是最简单的缓存,核心在于:现在缓存集合中找数据,如果没找到再去数据库中获取。上面是无法进行多线程应用的,所以可以讲方法改成synchronized。然而这并不是最佳的处理多线程的方式,因为获取数据的过程只有2步:读缓存,(读数据库和写缓存)。那么可以考虑使用读写锁机制,新版本如下:

public class CacheDemo

{

private Map<String, Object> cache = new HashMap<String, Object>();

private ReadWriteLock rwl = new ReentrantReadWriteLock();

publicObject getData(String key)

{

// 首先上读锁

rwl.readLock().lock();

// 首先从缓存中获取

Object value = null;

try

{

Thread.sleep(1000);

value = cache.get(key);

if (value == null)

{

// 如果缓存中没有数据,那么就从数据库中获取

// 但此时需要上写锁,只需要让一个进程进行写数据

// 首先去除读锁,然后加上写锁

rwl.readLock().unlock();

rwl.writeLock().lock();

try

{

//此处是亮点,防止多线程运行到上一步,某个线程写完数据后

//别的线程就需要看是否有数据再决定是否进行写操作

//在写之前再读一次,防止最开始的线程都进行写操作

value = cache.get(key);

// 第一个线程写完后,防止后面的线程再次写数据

if (value == null)

{

System.out.println("有线程写数据........");

value = "数据库中获取";

// 将数据放入缓存

cache.put(key, value);

System.out.println("数据写完了.......");

}

} finally

{

rwl.writeLock().unlock();

}

rwl.readLock().lock();

}

} catch (InterruptedException e)

{

// TODO Auto-generated catch block

e.printStackTrace();

} finally

{

rwl.readLock().unlock();

}

return value;

}

}