• 【深入Java基础】HashMap的高级用法(二):同步


    HashMap的高级用法:同步

    HashMap是不支持同步的,不能用于多线程中。而HashTable是同步的,这个日后再论。我们可以使用以下两种方法来实现HashMap的同步:

    • 使用ConcurrentHashMap

    • 使用Collections.synchronizedMap获取同步map

    使用ConcurrentHashMap

        ConcurrentHashMap<Integer,String> concurrentHashMap = new ConcurrentHashMap<>();

    使用Collections.synchronizedMap获取同步map

        HashMap<Integer,String> hashMap = new HashMap<>();
        Map<Integer,String> synchronizedMap = Collections.synchronizedMap(hashMap);

    测试

    对于没有同步的HashMap在多线程中运行一定会抛出异常:

        java.util.ConcurrentModificationException

    运行两个线程同时对一个hashmap进行读写操作:

        HashMap<Integer,String> hashMap1 = new HashMap<>();
            //写线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 1000; i++) {
                        hashMap1.put(i,"value"+i);
                        try {
                            Thread.sleep(new Random().nextInt(10));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
            //读线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        if (hashMap1.size() > 0) {
                            for (Map.Entry entry : hashMap1.entrySet()) {
                                System.out.println(entry.getKey() + "=" + entry.getValue());
                            }
                        }
                        try {
                            Thread.sleep(new Random().nextInt(10));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();

    运行以上代码抛出异常java.util.ConcurrentModificationException。原因是未实现同步时,在迭代hashmap的时候不能修改数据。

    Collections.synchronizedMap实现同步:

        HashMap<Integer,String> hashMap1 = new HashMap<>();
            Map<Integer, String> map = Collections.synchronizedMap(hashMap1);
            //写线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 1000; i++) {
                        map.put(i,"value"+i);
                        try {
                            Thread.sleep(new Random().nextInt(10));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
            //读线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        if (map.size() > 0) {
                            for (Map.Entry entry : map.entrySet()) {
                                System.out.println(entry.getKey() + "=" + entry.getValue());
                            }
                        }
                        try {
                            Thread.sleep(new Random().nextInt(10));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();

    运行以上代码任然抛出异常java.util.ConcurrentModificationException。可见该方法并不安全。(还是这样测试有问题?)

    ConcurrentHashMap实现同步:

          ConcurrentHashMap<Integer,String> concurrentHashMap = new ConcurrentHashMap<>();
           //写线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 1000; i++) {
                        concurrentHashMap.put(i,"value"+i);
                        try {
                            Thread.sleep(new Random().nextInt(10));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
            //读线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        if (concurrentHashMap.size() > 0) {
                            for (Map.Entry entry : concurrentHashMap.entrySet()) {
                                System.out.println(entry.getKey() + "=" + entry.getValue());
                            }
                        }
                        try {
                            Thread.sleep(new Random().nextInt(10));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();

    运行以上代码,无异常。

    所以为了保证多线程下的hashmap的数据一致性使用ConcurrentHashMap最为合理。并且ConcurrentHashMap的效率也比较高。为什么日后再论。

    使用lock锁手动实现hashmap的同步:

         ReentrantLock lock = new ReentrantLock(true);
         HashMap<Integer, String> hashMap1 = new HashMap<>();
    
                //写线程
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                        for (int i = 0; i < 1000; i++) {
                            hashMap1.put(i, "value" + i);
                            try {
                                Thread.sleep(new Random().nextInt(10));
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        } catch (Exception e) {
    
                        } finally {
                            //lock.unlock();
                        }
                    }
                }).start();
    
    
            //读线程
            new Thread(new Runnable() {
                @Override
                public void run() {
    
                    while (true) {
                        lock.lock();
                        try {
                            if (hashMap1.size() > 0) {
                                for (Map.Entry entry : hashMap1.entrySet()) {
                                    System.out.println(entry.getKey() + "=" + entry.getValue());
                                }
                            }
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        } finally {
                            lock.unlock();
                        }
    
    
                        try {
                            Thread.sleep(new Random().nextInt(10));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
  • 相关阅读:
    json、txt、xlsx
    word-排版准备与文字清洗
    运营能力分析
    获利能力分析
    偿债能力分析
    现金流量表结构分析
    负债项目分析
    资产负债表分析
    财务报表的分析
    会计电算化账务处理流程8
  • 原文地址:https://www.cnblogs.com/cnsec/p/13286733.html
Copyright © 2020-2023  润新知