redis之双重检查锁(double check lock)的使用
2018-03-13 22:50
435 查看
通常使用redis的使用如下:public List<Order> query(){//1.查询缓存ValueOperations ops = redisTemplate.opsForValue();String json = String.valueOf(ops.get(CACHE_KEY));//2.判断缓存中是否有数据if(!StringUtils.isEmpty(json) || !json.equalsIgnoreCase("null")){//返回缓存数据logger.info("----query for cache----------");return JSON.parseArray(json,Order.class);}//3.查看数据库,并且返回数据,同时更新缓存List<Order> list = orderMapper.getAll();ops.set(CACHE_KEY,JSON.toJSON(list),10, TimeUnit.MINUTES);return list;}当使用多线程 CountDownLatch测试时,会造成缓存击穿代码如下:public class CacheTest2 {private static final Logger logger = LoggerFactory.getLogger(CacheTest2.class);private static final int THREAD_NUM = 10;//倒计时器private CountDownLatch cdl = new CountDownLatch(THREAD_NUM);@Autowiredprivate CacheService cacheService;public void testCache2() throws Exception{for (int i = 0; i < THREAD_NUM; i++) {new Thread(new QueryTask()).start();cdl.countDown();}//主线程休眠 也可以考虑用joinThread.currentThread().sleep(5000);//结果:并发导致缓存失效,使用策略 double check lock (SpringCache)}private class QueryTask implements Runnable{@Overridepublic void run() {try {cdl.await();} catch (InterruptedException e) {e.printStackTrace();}List<Order> list = cacheService.query();logger.info(list.toString());}}}使用双重检查锁:public /*synchronized */List<Order> query(){//1.查询缓存ValueOperations ops = redisTemplate.opsForValue();String json = String.valueOf(ops.get(CACHE_KEY));//2.判断缓存中是否有数据if(!StringUtils.isEmpty(json) || !json.equalsIgnoreCase("null")){//返回缓存数据logger.info("----query for cache----------");return JSON.parseArray(json,Order.class);}//Spring Cache//double check locksynchronized (this){json = String.valueOf(ops.get(CACHE_KEY));if(!StringUtils.isEmpty(json) || !json.equalsIgnoreCase("null")){//返回缓存数据logger.info("----query for cache----------");return JSON.parseArray(json,Order.class);}//3.查看数据库,并且返回数据,同时更新缓存List<Order> list = orderMapper.getAll();ops.set(CACHE_KEY,JSON.toJSON(list),10, TimeUnit.MINUTES);return list;}}封装成redis缓存查询模板1.查询接口public interface CacheLoadable<T> {public T load();}2.查询Servicepublic List<Order> queryByTemplate(){return cacheTemplateService.findCache(CACHE_KEY, 10, TimeUnit.MINUTES,new TypeReference<List<Order>>() {}, new CacheLoadable<List<Order>>() {@Overridepublic List<Order> load() {return orderMapper.getAll();}});}3.封装成模板@Componentpublic class CacheTemplateService {@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate OrderMapper orderMapper;public static final Logger logger = LoggerFactory.getLogger(CacheTemplateService.class);public <T> T findCache(String key, long expire, TimeUnit timeUnit,TypeReference<T> clazz, CacheLoadable<T> cacheLoadable){ValueOperations ops = redisTemplate.opsForValue();String json = String.valueOf(ops.get(key));if(!StringUtils.isEmpty(json) || !json.equalsIgnoreCase("null")){//返回缓存数据logger.info("----query for cache----------");return JSON.parseObject(json,clazz);}synchronized (this){json = String.valueOf(ops.get(key));if(!StringUtils.isEmpty(json) || !json.equalsIgnoreCase("null")){logger.info("----query for cache----------");return JSON.parseObject(json,clazz);}//核心业务T result = cacheLoadable.load();//2-3sops.set(key,JSON.toJSON(result),expire, timeUnit);return result;}}}
相关文章推荐
- Java 单例模式中使用双重检查(Double-Check)
- Java并发编程实战--双重检查加锁( double check lock)与延迟初始化占位
- java中的双重锁定检查(Double Check Lock)
- Java并发编程:volatile关键字解析 和双重检查(Double-Check)
- java中的双重检查模式(double-check idiom)
- Java 中的双重检查(Double-Check)
- Java 中的双重检查(Double-Check)
- 单例模式中的 双重检查锁定(Double-Check Locking )
- Java 中的双重检查(Double-Check)
- Java 中的双重检查(Double-Check)
- Java 中的双重检查(Double-Check)
- 单例模式中的 双重检查锁定(Double-Check Locking )
- Java 中的双重检查(Double-Check)
- Java 中的双重检查(Double-Check)
- Java 中的双重检查(Double-Check)
- 单例模式中的 双重检查锁定(Double-Check Locking ) (多线程下单例模式中的双重检查锁定的实现)
- Java中的双重检查(Double-Check)详解
- 单例模式中的 双重检查锁定(Double-Check Locking ) (多线程下单例模式中的双重检查锁定的实现)
- 单例模式的两种实现方式对比:DCL (double check idiom)双重检查 和 lazy initialization holder class(静态内部类)
- 单例(Singleton) 双重锁定(Double-Check Locking)