美文网首页
线程安全list的遍历

线程安全list的遍历

作者: M_lear | 来源:发表于2022-07-11 11:25 被阅读0次

Vector

Vector在迭代器遍历时,其他线程增删元素,会抛ConcurrentModificationException。

public class Main {
    public static void main(String[] args) {
        List<Integer> list = new Vector<>(Arrays.asList(1, 2, 3, 4, 5));

        ExecutorService executorService = Executors.newFixedThreadPool(3);

        executorService.execute(() -> {
            while (true) {
                for (Integer e : list) {
                    System.out.println(e);
                }
            }
        });

        executorService.execute(() -> {
            for (int i = 0; i < 100; ++i) {
                list.add(i);
            }
        });
    }
}

运行结果:

image.png

Vector迭代器没有创建拷贝,直接在存储元素的数组上迭代。

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

每次迭代前,都会检查是否在其他线程进行过增删,如果有,直接抛出ConcurrentModificationException。

Collections.synchronizedList

和Vector一样,会抛ConcurrentModificationException。

public class Main {
    public static void main(String[] args) {
        List<Integer> list = Collections.synchronizedList(
                new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)));

        ExecutorService executorService = Executors.newFixedThreadPool(3);

        executorService.execute(() -> {
            while (true) {
                for (Integer e : list) {
                    System.out.println(e);
                }
            }
        });

        executorService.execute(() -> {
            for (int i = 0; i < 100; ++i) {
                list.add(i);
            }
        });
    }
}

运行结果:


image.png

Collections.synchronizedList直接使用的是被包装list自生的迭代器。在我们这个例子中使用的就是ArrayList的迭代器。像ArryaList、LinkedList这些,在迭代时,其他线程增删,都会抛ConcurrentModificationException。

        public Iterator<E> iterator() {
            return c.iterator(); // Must be manually synched by user!
        }

CopyOnWriteArrayList

CopyOnWriteArrayList是在创建迭代器时的数组快照(这个数组上不会有增删改任何写操作)上迭代的,不会抛ConcurrentModificationException。

        public E next() {
            if (! hasNext())
                throw new NoSuchElementException();
            return (E) snapshot[cursor++];
        }

相关文章

网友评论

      本文标题:线程安全list的遍历

      本文链接:https://www.haomeiwen.com/subject/pvqnbrtx.html