先改造
package com.study.framework.annotation;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @Description: 自定义,线程安全的 map ,用读写锁改造HashMap
* @Auther: BacHe
* @Date: 2019/9/19 09:46
*/
public class SafeMap {
//非线程安全的map
private static Map<String, Object> map = new HashMap<>();
//可重入读写锁
private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
//读锁
private static Lock r = lock.readLock();
//写锁
private static Lock w = lock.writeLock();
//获取一个key 对应的值
public static final Object get(String key) {
//加 读锁
r.lock();
Object obj = null;
try {
obj = map.get(key);
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放锁
r.unlock();
}
return obj;
}
//设置 key 对应的value
public static final Object put(String key, Object value) {
//加 写锁
w.lock();
Object obj = null;
try {
obj = map.put(key, value);
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放锁
w.unlock();
}
return obj;
}
//清空所有的内容
public static final void clear() {
//加 写锁
w.lock();
try {
map.clear();
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放锁
w.unlock();
}
}
}
知识兔测试一下是不是线程安全
package com.study.framework;
import com.study.framework.annotation.SafeMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Description:
* @Auther: BacHe
* @Date: 2019/9/19 10:09
*/
public class SafeMapTest {
public static void main(String[] args) {
//定义原子变量
AtomicInteger integer = new AtomicInteger(0);
//定义写入线程
for (int i = 0; i < 1; i++) {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(1200);
} catch (InterruptedException e) {
e.printStackTrace();
}
int andAdd = integer.getAndAdd(1);
Object a = SafeMap.put("a", String.valueOf(andAdd));
if (null == a) {
a = "null";
}
System.out.println(Thread.currentThread().getName() + ",---上一个值:" + a.toString()
+",---put入:" + String.valueOf(andAdd));
}
}
},"写线程:"+String.valueOf(i+1)).start();
}
//定义读取线程
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object a = SafeMap.get("a");
if (null != a) {
System.out.println(Thread.currentThread().getName() + ",----" + a.toString());
} else {
System.out.println(Thread.currentThread().getName() + ",----null");
}
}
}
}, "读线程:" + String.valueOf(i + 1)).start();
}
}
}
知识兔观察输出结果,确实是读的时候不会写,写的时候不会读。避免出现脏读现象。
null
读线程:2,----null
读线程:3,----null
读线程:3,----null
读线程:2,----null
读线程:1,----null
写线程:1,---上一个值:null,---put入:0
读线程:1,----0
读线程:2,----0
读线程:3,----0
读线程:2,----0
读线程:1,----0
读线程:3,----0
写线程:1,---上一个值:0,---put入:1
读线程:3,----1
读线程:2,----1
读线程:1,----1
读线程:3,----1
读线程:1,----1
读线程:2,----1
读线程:1,----1
读线程:2,----1
读线程:3,----1
写线程:1,---上一个值:1,---put入:2
读线程:1,----2
读线程:3,----2
读线程:2,----2
读线程:1,----2
读线程:2,----2
读线程:3,----2
写线程:1,---上一个值:2,---put入:3
读线程:2,----3
读线程:1,----3
读线程:3,----3
读线程:3,----3
读线程:1,----3
读线程:2,----3
写线程:1,---上一个值:3,---put入:4
读线程:1,----4
读线程:3,----4
读线程:2,----4
读线程:3,----4
读线程:2,----4
读线程:1,----4
读线程:1,----4
读线程:3,----4
读线程:2,----4
写线程:1,---上一个值:4,---put入:5
读线程:2,----5
读线程:3,----5
读线程:1,----5
读线程:1,----5
读线程:2,----5
读线程:3,----5
写线程:1,---上一个值:5,---put入:6
读线程:1,----6
读线程:3,----6
读线程:2,----6
读线程:1,----6
读线程:2,----6
读线程:3,----6
读线程:1,----6
读线程:3,----6
读线程:2,----6
写线程:1,---上一个值:6,---put入:7
读线程:3,----7
读线程:2,----7
读线程:1,----7
读线程:1,----7
读线程:3,----7
读线程:2,----7
写线程:1,---上一个值:7,---put入:8
读线程:2,----8
读线程:1,----8
读线程:3,----8
读线程:2,----8
读线程:1,----8
读线程:3,----8
写线程:1,---上一个值:8,---put入:9
读线程:2,----9
读线程:1,----9
读线程:3,----9
读线程:3,----9
读线程:1,----9
读线程:2,----9
读线程:2,----9
读线程:3,----9
读线程:1,----9
写线程:1,---上一个值:9,---put入:10
读线程:3,----10
读线程:2,----10
读线程:1,----10
读线程:3,----10
读线程:1,----10
读线程:2,----10
写线程:1,---上一个值:10,---put入:11
读线程:3,----11
读线程:1,----11
读线程:2,----11
读线程:3,----11
读线程:2,----11
读线程:1,----11
知识兔嗯,就是这样。