先改造

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();
        }
    }
}

观察输出结果,确实是读的时候不会写,写的时候不会读。避免出现脏读现象。

读线程:1,----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

嗯,就是这样。

01-19 10:44