洞察管理小程序实例的关键在于实现跨平台能力与数据安全,如何利用FinClip助力企业在数字化转型中既合规又高效?
510
2022-10-19
聊聊Mybatis的缓存之装饰者模式
@[TOC]
聊聊Mybatis的缓存之装饰者模式
装饰器的Component被装饰者
Cache接口:
public interface Cache { String getId(); void putObject(Object key, Object value); Object getObject(Object key); Object removeObject(Object key); void clear(); int getSize(); default ReadWriteLock getReadWriteLock() { return null; } }
PerpetualCache实现了这个接口,使用HashMap来缓存数据
Cache是装饰器模式的Component接口,PerpetualCache是接口的实现类
装饰器模式的装饰者
BlockingCache实现了Cache接口,具有阻塞线程的功能,看一下它的获取缓存数据的方法:
@Override public Object getObject(Object key) { acquireLock(key); Object value = delegate.getObject(key); if (value != null) { releaseLock(key); } return value; }
先调用acquireLock()方法获取key对应的锁 调用被装饰者的getObject()方法 当获取到的值不为空的时候释放锁,为空就不释放锁了 返回key对应的value值
获取锁BlockingCache的acquireLock()方法:
private final ConcurrentHashMap
创建CountDownLatch对象,key和CountDownLatch对象进行关联,ConcurrentHashMap用来保存key和CountDownLatch的关联 如果CountDownLatch对象为空,说明ConcurrentHashMap没有key对应的CountDownLatch对象,就没有竞争,锁获取成功 如果CountDownLatch对象不为空,说明发生了竞争,就阻塞当前线程,直到latch.countDown()方法来进行唤醒
看下releaseLock()方法:
private void releaseLock(Object key) { CountDownLatch latch = locks.remove(key); if (latch == null) { throw new IllegalStateException("Detected an attempt at releasing unacquired lock. This should never happen."); } latch.countDown(); }
删除ConcurrentHashMap中key和CountDownLatch对象的关联 唤醒等待的线程
在真正使用的时候,线程之间产生竞争,线程a发现key没有关联的CountDownLatch对象,获取锁成功,获取锁成功后在ConcurrentHashMap集合中维护key和CountDownLatch对象的关联,线程b进入是没办法获取锁的,产生阻塞,这时候需要查询数据库的数据并调用putObject()方法来释放锁,从而线程b被唤醒
总结
本篇文章主要从装饰者模式的角度分析了一下缓存模块的被装饰器接口Cache和实现类PerpetualCache,PerpetualCache通过HasnMap来缓存数据,还介绍了一个装饰器BlockingCache,分析了它获取缓存的逻辑:先获取key对应的锁然后获取数据最后释放锁,CountDownLatch中保存key和CountDownLatch对象的关联来表示加锁是否成功
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~