如何在中间中断putAll操作以生成ConcurrentModificationException

时间:2014-05-21 12:02:16

标签: java multithreading collections concurrentmodification

我想重现一个场景,其中有两个线程访问共享的HashMap。当一个线程使用putAll()操作将共享映射的内容复制到localMap时,第二个线程会更改共享映射,并且应该抛出CocurrentModificationException。

我已尝试但无法在putAll操作运行时重现异常。每次putAll在其他线程进行修改之前完成或者在其他线程修改之后调用putAll。

有人可以建议我如何在java中生成场景?

感谢。

3 个答案:

答案 0 :(得分:0)

旋转两个线程,让它们连续运行。

让一个线程不断地执行putAll,另一个线程不断地进行修改。

答案 1 :(得分:0)

import java.util.HashMap;
import java.util.Map;

public class Example {
    private final HashMap<String, String> map = new HashMap<String, String>();

    public static void main(String[] args) {
        new Example();
    }

    public Example() {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                int counter = 0;
                while (true) {
                    Map<String, String> tmp = new HashMap<String, String>();
                    tmp.put("example" + counter, "example");
                    counter++;
                    map.putAll(tmp);
                }
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    map.values().remove("example");
                }
            }
         });

        thread1.start();
        thread2.start();
    }
}

不幸的是,我无法直接从当前工作站复制/粘贴正在运行的代码,因此我在此处重新输入,因此可能存在输入错误。

正如您所看到的,第一个线程不断添加值,而第二个线程迭代Map中的值。当它开始迭代值时,它需要许多值(该值在迭代器的构造中初始化)。但是,因为当Iterator在实际执行删除代码时检查映射中的实际值时,thread1会不断添加项,所以此值不是预期的。这会导致ConcurrentModificationException。

答案 2 :(得分:0)

如果您只需要抛出CocurrentModificationException,那么您可以实施自己的Map实施(HackedMap),以便在{{1}时从HashMap中删除项目尝试复制HashMap

中的值