zoukankan      html  css  js  c++  java
  • ReentrantReadWriteLock可重入读写锁改造HashMap的简单使用

    先改造

    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
    

    嗯,就是这样。
    虽然用读写锁,改造了hashmap ,但是这是任何的key都会加上读写锁,控制上还是不够精细,可以优化成相同的key 才会有竞争关系,有竞争关系才需要加读写锁。
    更精细的控制就能让性能再提高一个层次。

  • 相关阅读:
    递归函数及Java范例
    笔记本的硬盘坏了
    “References to generic type List should be parameterized”
    配置管理软件(configuration management software)介绍
    WinCE文件目录定制及内存调整
    使用Silverlight for Embedded开发绚丽的界面(3)
    wince国际化语言支持
    Eclipse IDE for Java EE Developers 与Eclipse Classic 区别
    WinCE Heartbeat Message的实现
    使用Silverlight for Embedded开发绚丽的界面(2)
  • 原文地址:https://www.cnblogs.com/itbac/p/11548353.html
Copyright © 2011-2022 走看看