《Java测试》关于Map遍历移除在多线程下的测试

    1.在java 中,for-each只适用于遍历,当要对集合进行操作的时候,就会导致错误,在java源码中可以看到相关的原因,因为对集合的操作都会导致modCount++,当迭代的时候回检查这个值。所以在**移除遍历移除map中的元素时就不能用迭代器**。

所以,就需要for循环进行遍历,大致是这样的

            Set setKeys = maps.keySet();
            //做移除时不能使用迭代器   
            Object[] keys = setKeys.toArray();
            for (int i = 0; i < keys.length; i++) {
                int value = maps.get(keys[i]);
                System.out.println(" 当前移除数据:\t"+ value);
                maps.remove(keys[i]);
            }

但是我用的时候在考虑,将set转换成数组的时候,是否仍是之前map的Key的引用,还是新的数组对象,因为我要在多线程时使用这个集合,就看是否数组中的key是否会随着其他线程插入数据而不一致,这时我还未看(toArray的实现源码)。

下面是测试代码,主线程移除数据,子线程添加数据:

public class ThreadMap {
    private Map maps = new HashMap<>();
    public static void main(String[] args) {
        new ThreadMap().test1();
    }

    public void test1(){

        for (int i = 0; i < 20; i++) {
            maps.put(i+"", i);
        }

        new AddNumThread().start();

        while(true){
            Set setKeys = maps.keySet();
            //做移除时不能使用迭代器   
            Object[] keys = setKeys.toArray();
            for (int i = 0; i < keys.length; i++) {
                int value = maps.get(keys[i]);
                System.out.println(" 当前移除数据:\t"+ value);
                maps.remove(keys[i]);
            }

            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //子线程
    class AddNumThread extends Thread{
        @Override
        public void run() {
            int number = 1000;
            while(true){
                for (int i = 0; i < 10; i++) {
                    System.out.println(" 当前放入数据:"+ number);
                    maps.put(""+number,number);
                    number++ ;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

测试结果:
《Java测试》关于Map遍历移除在多线程下的测试_第1张图片

可以看到子线程先放入 1000,但主线程在移除的时候并没有这个数据,将其移除,而是只移除了预先放入的20个数据。就表明这样写是可以的,转换成数组相当于只保存了当前的版本集合,移除时只作用在当前的时间点。获取时可能需要判断NULL。

你可能感兴趣的:(-----Java,程序设计-----)