博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
结合 ConcurrentHashMap.putIfAbsent 与 Futrue 实现本地缓存防击穿
阅读量:4081 次
发布时间:2019-05-25

本文共 1298 字,大约阅读时间需要 4 分钟。

http://blog.csdn.net/michaelwubo/article/details/50865185

Java 高并发缓存与Guava Cache

这篇文章名字叫《Java 高并发缓存与Guava Cache》,但最核心的是如何高效的防止本地缓存击穿

业务模型:

res = cache.get(key);if(res == null) {   value = sql;   cach.put(key, value);   return value;} return res;

这个代码多线程里不行:

在多线程时,出现了在缓存里没有缓存时,会执行一样执行多次的业务数据并返回处理的数据,我们分析一下出现这种情况的:

(1)当线程T1访问cacheMap里面有没有,这时根据业务到后台处理业务数据并返回处理数据,并放入缓存

(2)当线程T2访问cacheMap里面同样也没有,也把根据业务到后台处理业务数据并返回处理数据,并放入缓存

首先想到的是同步Synchronized
res = cache.get(key);if(res == null) {   synchronized(this) {      oldValue = cache.get(key);      if(oldValue == null) {         value = sql;         cach.put(key, value);         return value;      } else           return oldValue;   }} return res;
然后就会想到这个代码对性能损伤较大,而且不适用于集群环境。
缓存失效的瞬间,并发线程全部阻塞
然后重点来了:使用Future和ConcurrentMap异步更新缓存
res = cache.get(key);if(res == null) {   FutureTask
futureTask=new FutureTask
(callable); futureValue=cacheMap.putIfAbsent(keyValue, futureTask); if(futureValue==null){ futureValue=futureTask; futureTask.run(); } return futureValue.get();}return res;
假设现在缓存失效,并发线程5个,都创建了FutureTask,
putIfAbsent:如果(调用该方法时)key-value 已经存在,则返回那个 value 值。如果调用时 map 里没有找到 key 的 mapping,返回一个 null 值

故最终5个中只有一个线程能够得到真正的 执行-阻塞-返回 过程,其它4个线程可能有两种情况:

(1)阻塞-返回

(2)直接返回

比用syn同步块清一色阻塞要好得多了

你可能感兴趣的文章