【问题标题】:How to avoid ConcurrentModificationException while iterating over map.entrySet迭代 map.entrySet 时如何避免 ConcurrentModificationException
【发布时间】:2016-07-15 19:38:27
【问题描述】:

我有以下代码:

static final Map<String, String> map = Collections.synchronizedMap(new HashMap());

    public static void main(String[] args) throws InterruptedException {
        map.put("1", "1");
        map.put("2", "2");
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (Map.Entry<String, String> stringStringEntry : map.entrySet()) {
                    System.out.println("after iterator");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }
        }).start();

        Thread.sleep(50);
        map.remove("1");
        System.out.println("removed");
    }

它产生java.util.ConcurrentModificationException

如何避免?

【问题讨论】:

标签: java dictionary iterator concurrentmodification


【解决方案1】:

您不能在迭代集合时从集合中移除元素,除非您使用迭代器。使用 Iterator.remove() 方法

【讨论】:

  • 失败保存迭代器?
【解决方案2】:

你可以使用static final Map<String, String> map = new ConcurrentHashMap<>();

    static final Map<String, String> map = new ConcurrentHashMap<>();

public static void main(String[] args) throws InterruptedException {
    map.put("1", "1");
    map.put("2", "2");
    new Thread(new Runnable() {
        @Override
        public void run() {
            for (Map.Entry<String, String> stringStringEntry : map.entrySet()) {
                System.out.println("after iterator");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }).start();

    Thread.sleep(50);
    map.remove("1");
    System.out.println("removed");
}

【讨论】:

    【解决方案3】:

    如果您想迭代 Collections.synchronizedMap,您必须显式同步迭代:

            synchronized (map) {
                for (Map.Entry<String, String> stringStringEntry : map.entrySet()) {
                    System.out.println("after iterator");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                }
             }
    

    【讨论】:

    • 在这种情况下我可以使用简单的 HasMap
    • 没有。您必须同步地图上的迭代和所有其他操作,synchronizedMap 就是这样做的方式。
    猜你喜欢
    • 2014-02-25
    • 1970-01-01
    • 2017-11-27
    • 1970-01-01
    • 2013-08-29
    • 2018-05-09
    • 2021-11-23
    • 2017-05-30
    相关资源
    最近更新 更多