1 package cn.xxx.xxx;
2
3 import java.util.HashMap;
4 import java.util.Map;
5 import java.util.concurrent.locks.ReadWriteLock;
6 import java.util.concurrent.locks.ReentrantReadWriteLock;
7
8 public class CacheDemo_My {
9
10 public static void main(String[] args) {
11 // 内部类 实例化时需要在 内部类前加static 关键字
12 final CacheClass cacheClass = new CacheClass();
13 for (int i = 0; i < 10; i++) {
14 new Thread(new Runnable() {
15
16 @Override
17 public void run() {
18 Object valueObject = cacheClass.getData("1");
19 System.out.println(Thread.currentThread().getName() + " : " + valueObject);
20 }
21 }).start();
22 }
23 }
24
25
26 static class CacheClass {
27 private Map<String, Object> cacheMap = new HashMap<String, Object>();
28
29 /**
30 * 1.0 没有考虑并发 问题: 从数据库查了两次
31 * 从数据库查询数据!
32 * 从数据库查询数据!
33 * Thread-1 : null 为什么是null,并发了,过程如 Thread-0 所示
34 * Thread-2 : aaa
35 * Thread-0 :null 为什么是null,因为第一次读取map中没有值返回null,而cacheMap.put(key, "aaa")后
36 * 并没有重新赋值给object 所以是null
37 * 解决方案是 直接从cacheMap.get(key) 中获取,不要中间环节 object,这里我就不改了
38 * Thread-3 : aaa
39 * Thread-4 : aaa
40 * Thread-5 : aaa
41 * Thread-6 : aaa
42 * Thread-7 : aaa
43 * Thread-8: aaa
44 * Thread-9 : aaa
45 *
46 * @param key
47 * @return
48 */
49 // public Object getData(String key) {
50 // Object value = cacheMap.get(key);
51 // if (value == null) {
52 // System.out.println("从数据库查询数据!");
53 // cacheMap.put(key, "aaa");
54 // }
55 // return value;
56 // }
57
58 /**
59 * 2.0 使用synchronized 同步 代码块 解决并发问题 实现方式简单 直接加synchronized 关键字
60 *
61 * 从数据库查询数据!
62 * Thread-4 : bbb
63 * Thread-1 : bbb
64 * Thread-2 : bbb
65 * Thread-0 : bbb
66 * Thread-3 : bbb
67 * Thread-8 : bbb
68 * Thread-7 : bbb
69 * Thread-6 : bbb
70 * Thread-9 : bbb
71 * Thread-5 : bbb
72 *
73 * @param key
74 * @return
75 */
76 // public synchronized Object getData(String key){
77 //
78 // if ( cacheMap.get(key)==null) {
79 // System.out.println("从数据库查询数据!");
80 // cacheMap.put(key, "bbb");
81 // }
82 // return cacheMap.get(key);
83 // }
84
85 /**
86 * 3.0 使用读写锁
87 *
88 从数据库查询数据!
89 Thread-1 : ccc
90 Thread-3 : ccc
91 Thread-4 : ccc
92 Thread-2 : ccc
93 Thread-0 : ccc
94 Thread-5 : ccc
95 Thread-7 : ccc
96 Thread-8 : ccc
97 Thread-9 : ccc
98 Thread-6 : ccc
99 */
100 private ReadWriteLock rwl = new ReentrantReadWriteLock();
101 public Object getData(String key) {
102 //加锁了就要try finally ,避免异常情况下 代码一直被锁
103 rwl.readLock().lock();
104 try {
105 if (cacheMap.get(key) == null) {
106 try{
107 //读锁 解掉 是为了写锁 加锁
108 rwl.readLock().unlock();
109 //加锁了就要try finally ,避免异常情况下 代码一直被锁
110 rwl.writeLock().lock();
111 // 避免第一个线程写完数据,后面的线程接着写
112 if (cacheMap.get(key) == null) {
113 System.out.println("从数据库查询数据!");
114 cacheMap.put(key, "ccc");
115 }
116 }
117 finally{
118 rwl.writeLock().unlock();
119 }
120 rwl.readLock().lock();
121 }
122 } finally {
123 rwl.readLock().unlock();
124 }
125
126 return cacheMap.get(key);
127 }
128 }
129 }