背景
jdk1.8之前是没有线程安全的集合工具类,例如
currentHashMap
,那怎样实现高效、线程安全的集合工具类呢?
可以利用读写锁实现线程安全,动态代理帮助集合作为工具类,产生更多的使用场景,例如缓存
代码
1. 创建缓存基类和子类
基类里的读写锁
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public void readLock() {
try {
readWriteLock.readLock().lock();
} catch (Exception e) {
throw new CacheRuntimeException(e);
}
}
public void releaseRead(){
readWriteLock.readLock().unlock();
}
public void writeLock() {
try {
readWriteLock.writeLock().lock();
} catch (Exception e) {
throw new CacheRuntimeException(e);
}
}
public void releaseWrite(){
readWriteLock.writeLock().unlock();
}
复制
子类里的基本方法
private HashBiMap<Integer,String> idAndNameBiMap;
public void init() {
idAndNameBiMap= HashBiMap.create();
System.out.println("idAndNameBiMap init");
}
public Integer getIdByName(String name){
System.out.println("getIdByName");
return idAndNameBiMap.inverse().get(name);
}
public String getNameById(Integer id){
System.out.println("getNameById");
return idAndNameBiMap.get(id);
}
public void putIdAndName(Integer id,String name){
System.out.println("putIdAndName");
idAndNameBiMap.put(id, name);
}
复制
2. 动态代理实现子类的增强
1. 创建代理类
public synchronized AbstractCacheImpl getTarget() {
if (targetCrated) {
return target;
}
if (ClassUtils.isAssignable(this.cacheImpl, AbstractCacheImpl.class)) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.cacheImpl);
enhancer.setCallback(this);
target = (AbstractCacheImpl) enhancer.create();
target.setCallbackId(getProxyName());
if (MapUtil.isNotEmpty(cacheProperties)) {
BeanUtil.fillBeanWithMap(cacheProperties, target, false);
}
} else {
throw new CacheRuntimeException(
"cacheImpl isn't a subclass of AbstractCacheImpl" + this);
}
initCache();
targetCrated = true;
return target;
}
复制
2. 方法拦截器
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
try {
AbstractCacheImpl cache = (AbstractCacheImpl) o;
Object retFromSuper = null;
if (ignoreMethods.contains(method.getName())) {
retFromSuper = methodProxy.invokeSuper(cache, objects);
} else if (writeMethod.contains(method.getName())) {
System.out.println("writeLock:"+method.getName());
cache.writeLock();
try {
retFromSuper = methodProxy.invokeSuper(cache, objects);
} finally {
cache.releaseWrite();
System.out.println("releaseWrite");
}
} else if (readMethod.contains(method.getName())) {
System.out.println("readLock:"+method.getName());
cache.readLock();
try {
retFromSuper = methodProxy.invokeSuper(cache, objects);
} finally {
cache.releaseRead();
System.out.println("releaseRead");
}
} else {
retFromSuper = methodProxy.invokeSuper(cache, objects);
}
return retFromSuper;
} catch (Exception e) {
throw new RuntimeException(e).fillInStackTrace();
}
}
复制
3. 验证
1. 将动态代理类注入IOC容器
@Configuration
public class UserCacheConfigration {
@Bean("userCacheBean")
public CacheProxy userCacheBean() {
return CacheProxy.builder()
.proxyName("userCache")
// 缓存子类的初始化方法
.initMethod("init")
// 缓存子类
.cacheImpl(UserCache.class)
// 需要上读锁的方法
.readMethod(Sets.newHashSet("getNameById"))
// 需要上写锁的方法
.writeMethod(Sets.newHashSet("putIdAndName"))
.build();
}
}
复制
2. 单元测试
@Test
public void testUserCache(){
UserCache target = (UserCache) cacheProxy.getTarget();
target.putIdAndName(1,"张三");
target.putIdAndName(2,"李四");
System.out.println(target.getIdByName("张三"));
System.out.println(target.getNameById(2));
}
复制