今天看完mybatis所有缓存装饰类,总结整理一下
文章目录
1、BlockingCache
上篇已经说了,BlockingCache 它特点就是不同缓存key会阻塞,如果一个线程没有获取某个key对应value,它就不会释放锁,它锁采用是ReentrantLock(重入锁),同一个线程可以加锁多次,但是也必须解锁相同的次数,其他线程才可访问该key,进行加锁。
2、FifoCache(先进先出缓存装饰类)
- 它的实现是通过LinkedList双队列方式存入缓存的key,一端放入最新缓存的key,如果超过阈值,就在另一端移除缓存key
- 默认大小队列的大小是1024
3、LoggingCache(日志缓存装饰类)
- 设计主要目的是在debug模式调试某个缓存的命中率,也就是
- 命中率=获取到值次数/请求次数
4、LruCache(最近最少使用缓存装饰类)
- 设计思路就是用进废退思想,经常用会放在前面不会被清除掉(通过put或get方法获取某个缓存key对象,那么这个缓存key自动排在最前面)
- 默认的大小也是1024
- 它是采用LinkedHashMap实现的,重写removeEldestEntry的方法,判断当前缓存key的个数是否超过阈值,如果超过了,就获取到最不经常用的key,在下一次put的时候,进行移除该key的缓存对象
测试代码
/**
* 默认大小是1024, 会清除索引为0数据
* 最新操作的元素总是放在最后位置, 从前面删除元素
* @param args
*/
public static void main(String[] args) {
LruCache lruCache = new LruCache(new PerpetualCache("com.jack.pa"));
lruCache.setSize(3);
lruCache.putObject(1, 1);
lruCache.putObject(2, 2);
lruCache.putObject(3, 3); // 123
lruCache.putObject(4, 4); // 234
lruCache.getObject(3); // 243
for (Map.Entry<Object, Object> entry : lruCache.keyMap.entrySet()) {
System.out.println("key:"+ entry.getKey() + " value:" + entry.getValue());
}
}
5、ScheduledCache(定间隔清理缓存装饰类)
- 第一它并没有定时任务去清除缓存,只是调用这个方法才会真正的清除
- 默认缓存清除时间是1小时
/**
* 立即获取:1
延迟2秒获取:null
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
ScheduledCache scheduledCache = new ScheduledCache(new PerpetualCache("com.jack.pa"));
scheduledCache.setClearInterval(1000);
scheduledCache.putObject(1,1);
System.out.println("立即获取:" + scheduledCache.getObject(1));
Thread.sleep(2000);
System.out.println("延迟2秒获取:" + scheduledCache.getObject(1));
}
6、SerializedCache(序列化缓存装饰类)
- 本质就是把对象以byte[] 数组存入缓存对象中
- 缓存对象必须要实现serializable接口
- 自定义ObjectInputStream 重写resolveClass方法, 使用自己Resource获取Class类
/**
* 把缓存的对象采用byte[]数组进行存储
* @param args
*/
public static void main(String[] args) {
LruCache serializedCache = new LruCache(new SerializedCache(new PerpetualCache("com.jack.pa")));
serializedCache.putObject("1121211","21132131312");
serializedCache.getObject("1121211");
}
7、SoftCache(软引用缓存装饰类)
- 一般用于内存比较敏感,当内存不够的时候,GC可以进清除这些缓存
- 里面有两个成员变量一个是避免GC回收集合(hardLinksToAvoidGarbageCollection),默认大小是256,一个关联GC收集(queueOfGarbageCollectedEntries)之后,将回收对象存入到ReferenceQueue中来标记该对象已经被回收,缓存真正去移除这个缓存对象
- hardLinksToAvoidGarbageCollection集合进行操作的是采用同步操作
8、WeakCache(弱引用缓存装饰类)
1.这个实现类似SoftCache,它比SoftCache更容易被GC回收
9、SynchronizedCache(同步缓存装饰类)
- 这个主要是在方法上加了synchronized关键来实现同步操作
10、TransactionCache(事务缓存装饰类)
- 这个是一个二级缓存事务的buffer
- put操作不会直接put到底层缓存对象中,而是put本对象中entriesToAddOnCommit
- 只有在commit操作之后才会将entriesToAddOnCommit刷新到底层缓存对象中
- 这个类支持BlockingCache,但是好像有bug
- entriesMissedInCache这个集合是存在没有获取到值的缓存key集合(Set集合)
/**
* 他说这个类支持BlockingCache,但是发现多次请求同一个key,导致多次加锁,但是这个entriesMissedInCache是Set集合
* 导致多次加锁之后还是存在一个对象,在解锁的时候只能解锁一次导致其他其他线程不能获取缓存key,所以认为这里可能有bug,把Set缓存List不会出现
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
BlockingCache blockingCache = new BlockingCache(new PerpetualCache("com.jack.pa"));
TransactionalCache transactionalCache = new TransactionalCache(blockingCache);
for(int i=0 ; i < 10; i++) {
transactionalCache.getObject(1);
}
transactionalCache.rollback();
Thread tryLock = new Thread(()->{
transactionalCache.getObject(1);
});
tryLock.start();
tryLock.join();
}
11、总结
- 除了PerpetualCache是真正缓存对象,也就是底层缓存对象,以上10种都是装饰类,丰富PerpetualCache功能,实现它的新特性。
- 装饰类的主要操作对象是缓存key,通过缓存key实现一些功能
- PerpetualCache底层是HashMap进行存储缓存