使用ReentrantReadWriteLock实现一个简单的缓存原理

之前说过Lock,ReentrantReadWriteLock是Lock的实现类,可以获取读锁与写锁。这里用ReentrantReadWriteLock做一个简单的缓存系统原理实现。

代码跟注释如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class CacheSystem {
public static void main(String[] args) {
CacheUtil cacheUtil = new CacheUtil();
cacheUtil.getObject("1");
}
}
class CacheUtil {
// 本地存放缓存对象的集合
private Map<String, Object> cacheMap = new HashMap<String, Object>();
// 读写锁
private ReadWriteLock rwl = new ReentrantReadWriteLock();
// 获取数据
public Object getObject(String id) {
// 先上读锁
rwl.readLock().lock();
Object object = null;
try {
object = cacheMap.get(id);
if (null == object) {
// 发现缓存集合中没有数据,释放读锁
rwl.readLock().unlock();
// 上写锁
rwl.writeLock().lock();
try {
if (null == object) {
object = "往数据库查询出数据";
cacheMap.put(id, object);
}
} finally {
rwl.writeLock().unlock();
System.out.println("写锁释放了!");
}
// 重新上读锁
System.out.println("重新上读锁了!");
rwl.readLock().lock();
}
} finally {
System.out.println("读锁释放了!");
rwl.readLock().unlock();
}
return object;
}
// 更新数据
public void updateObject(Object obj) {
//获取更新对象的ID
String id = "1";//伪代码obj.getId();
Object object = getObject(id);
//缓存中有数据,避免数据不一致。清空缓存保存的数据
if(null != object){
cacheMap.remove(id);
}
System.out.println("更新数据库中数据");
}
}

mybatis中的缓存

  • 一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。
  • 二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。二级缓存是以namespace来划分的,一个namespace有一个二级缓存。

一级缓存工作原理


查询时会创建一个唯一的Key。

查询缓存Map中是否有对象

更新时,执行删除缓存数据

一级缓存实现类PerpetualCache类

二级缓存需要单独配置,不做过多说明

mybatis提供了Cache接口,可对接不同的缓存厂商。如redis、memcached、ehcache。

谢谢你请我吃糖果

--------- 本文结束,感谢您的审阅 ---------
0%