package cn.xxx.xxx;

 import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; public class CacheDemo_My { public static void main(String[] args) {
// 内部类 实例化时需要在 内部类前加static 关键字
final CacheClass cacheClass = new CacheClass();
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() { @Override
public void run() {
Object valueObject = cacheClass.getData("1");
System.out.println(Thread.currentThread().getName() + " : " + valueObject);
}
}).start();
}
} static class CacheClass {
private Map<String, Object> cacheMap = new HashMap<String, Object>(); /**
* 1.0 没有考虑并发 问题: 从数据库查了两次
* 从数据库查询数据!
* 从数据库查询数据!
* Thread-1 : null 为什么是null,并发了,过程如 Thread-0 所示
* Thread-2 : aaa
* Thread-0 :null 为什么是null,因为第一次读取map中没有值返回null,而cacheMap.put(key, "aaa")后
* 并没有重新赋值给object 所以是null
* 解决方案是 直接从cacheMap.get(key) 中获取,不要中间环节 object,这里我就不改了
* Thread-3 : aaa
* Thread-4 : aaa
* Thread-5 : aaa
* Thread-6 : aaa
* Thread-7 : aaa
* Thread-8: aaa
* Thread-9 : aaa
*
* @param key
* @return
*/
// public Object getData(String key) {
// Object value = cacheMap.get(key);
// if (value == null) {
// System.out.println("从数据库查询数据!");
// cacheMap.put(key, "aaa");
// }
// return value;
// } /**
* 2.0 使用synchronized 同步 代码块 解决并发问题 实现方式简单 直接加synchronized 关键字
*
* 从数据库查询数据!
* Thread-4 : bbb
* Thread-1 : bbb
* Thread-2 : bbb
* Thread-0 : bbb
* Thread-3 : bbb
* Thread-8 : bbb
* Thread-7 : bbb
* Thread-6 : bbb
* Thread-9 : bbb
* Thread-5 : bbb
*
* @param key
* @return
*/
// public synchronized Object getData(String key){
//
// if ( cacheMap.get(key)==null) {
// System.out.println("从数据库查询数据!");
// cacheMap.put(key, "bbb");
// }
// return cacheMap.get(key);
// } /**
* 3.0 使用读写锁
*
从数据库查询数据!
Thread-1 : ccc
Thread-3 : ccc
Thread-4 : ccc
Thread-2 : ccc
Thread-0 : ccc
Thread-5 : ccc
Thread-7 : ccc
Thread-8 : ccc
Thread-9 : ccc
Thread-6 : ccc
*/
private ReadWriteLock rwl = new ReentrantReadWriteLock();
public Object getData(String key) {
//加锁了就要try finally ,避免异常情况下 代码一直被锁
rwl.readLock().lock();
try {
if (cacheMap.get(key) == null) {
try{
//读锁 解掉 是为了写锁 加锁
rwl.readLock().unlock();
//加锁了就要try finally ,避免异常情况下 代码一直被锁
rwl.writeLock().lock();
// 避免第一个线程写完数据,后面的线程接着写
if (cacheMap.get(key) == null) {
System.out.println("从数据库查询数据!");
cacheMap.put(key, "ccc");
}
}
finally{
rwl.writeLock().unlock();
}
rwl.readLock().lock();
}
} finally {
rwl.readLock().unlock();
} return cacheMap.get(key);
}
}
}

基于synchronized 或 ReadWriteLock实现 简单缓存机制的更多相关文章

  1. 常见面试题之操作系统中的LRU缓存机制实现

    LRU缓存机制,全称Least Recently Used,字面意思就是最近最少使用,是一种缓存淘汰策略.换句话说,LRU机制就是认为最近使用的数据是有用的,很久没用过的数据是无用的,当内存满了就优先 ...

  2. 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。

    基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...

  3. 简单的Map缓存机制实现

    大致思路是用一个单例的Map实现,当然此Map得是线程安全的--ConcurrentHashMap 原本项目需求是缓存十条消息,所以打算用Map实现缓存机制.中途夭折下面具体尚未实现... 当然此代码 ...

  4. 【腾讯Bugly干货分享】彻底弄懂 Http 缓存机制 - 基于缓存策略三要素分解法

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/qOMO0LIdA47j3RjhbCWUEQ 作者:李 ...

  5. Http协议:彻底弄懂 Http 缓存机制 - 基于缓存策略三要素分解法

    转载:http://mp.weixin.qq.com/s/uWPls0qrqJKHkHfNLmaenQ 导语 Http 缓存机制作为 web 性能优化的重要手段,对从事 Web 开发的小伙伴们来说是必 ...

  6. mybatis缓存机制

    目录 mybatis缓存机制 Executor和缓存 一级缓存 小结 二级缓存 小结 mybatis缓存机制 mybatis支持一.二级缓存来提高查询效率,能够正确的使用缓存的前提是熟悉mybatis ...

  7. Lock、synchronized和ReadWriteLock,StampedLock戳锁的区别和联系以及Condition

    https://www.cnblogs.com/RunForLove/p/5543545.html 先来看一段代码,实现如下打印效果: 1 2 A 3 4 B 5 6 C 7 8 D 9 10 E 1 ...

  8. 聊聊MyBatis缓存机制【美团-推荐】

    聊聊MyBatis缓存机制 2018年01月19日 作者: 凯伦 文章链接 18778字 38分钟阅读 前言 MyBatis是常见的Java数据库访问层框架.在日常工作中,开发人员多数情况下是使用My ...

  9. Volley源码解析(三) 有缓存机制的情况走缓存请求的源码分析

    Volley源码解析(三) 有缓存机制的情况走缓存请求的源码分析 Volley之所以高效好用,一个在于请求重试策略,一个就在于请求结果缓存. 通过上一篇文章http://www.cnblogs.com ...

随机推荐

  1. ip地址转换

    通常,我们用点分十进制字符串表示ipv4地址(192.168.1.1),用十六进制字符串表示ipv6地址(fe80::20c:29ff:fee9:4bcc). ipv4转换函数 #include &l ...

  2. NSIS对话框单位造成的控件移位问题

    在使用NSIS脚本开发安装卸载程序,使用自定义的nsdialog控件.发现在小部分系统上安装时,一些控件会消失,或者挪位.于是排除问题,看看这些控件的为位置和坐标,发现基本上是使用了对话框单位的控件, ...

  3. spark 快速入门 java API

    Spark的核心就是RDD,对SPARK的使用入门也就是对RDD的使用,包括action和transformation 对于Java的开发者,单单看文档根本是没有办法理解每个API的作用的,所以每个S ...

  4. mysql 命令导入导出

    导出 mysqldump -u 用户名 -p 数据库名 > 导出的文件名mysqldump -u root -p dataname >xxx.sql 导入 mysql>source ...

  5. memcache的内存管理探微

    slab分配器:http://blog.csdn.net/luotuo44/article/details/42737181 hash操作  :http://blog.csdn.net/luotuo4 ...

  6. mui学习记录

    1.页面间传值 2.mui如何增加自定义icon图标 http://ask.dcloud.net.cn/article/128 3.设计基于HTML5的APP登录功能及安全调用接口的方式(原理篇) h ...

  7. CC2540自己的配置文件

    首先要指出,字段属性有notify的不能同时有read,write属性,别问哥,哥也不知道,反正我做的就不能notify,只能read,write. 分享的程序段第一字段有notify属性,第二字段r ...

  8. js方法入参或局部变量和全局变量重名,用来赋值全局变量会失败

    今天遇到个bug,最后终于知道原因了,js方法入参和全局变量重名,用入参赋值全局变量失败,就是说方法入参不能和全局变量重名. 现在下面的例子也说明,局部变量和全局变量不可以同名不光是入参,只要同名赋值 ...

  9. java垃圾回收机制

    1 .垃圾回收机制(GC)垃圾回收就是回收内存中不再使用对象:(1)垃圾回收的步骤:1)查找内存中不再使用的对象:2)释放这些对象所占用的内存:(2)查找内存中不再使用的对象方法:1)引用计数法如果一 ...

  10. libsvm数据处理初略流程