CopyOnWriteArrayList не работает должным образом - PullRequest
1 голос
/ 09 июня 2019

Я учусь на CopyOnWriteArrayList, и он не работает в соответствии с моим пониманием. У меня есть две темы, одна из которых является основной, а другая внутренняя. Основной поток удаляет объекты из коллекции CopyOnWriteArrayList, пока внутренний поток спит в течение 5 секунд. Основной поток завершает операции удаления задолго до того, как внутренний поток выполняет итерацию, но внутренний поток все еще выполняет итерацию всей коллекции, я имею в виду, которые удаляются основным потоком.

package com.kalavakuri.javaconcurrent;

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class ConcurrentModificationExceptionExample {

    private static List<String> strings = new CopyOnWriteArrayList<String>();

    public static void main(String[] args) {

        strings.add("Ram");
        strings.add("Ravi");
        strings.add("Raju");
        strings.add("Raghu1");
        strings.add("Raghu2");
        strings.add("Raghu3");
        strings.add("Raghu4");
        strings.add("Raghu5");
        strings.add("Raghu6");

        Thread thread = new Thread(() -> {
            Iterator<String> iterator = strings.iterator();
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
                System.out.println("Thread name " + Thread.currentThread().getName());
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Inner thread");

        thread.start();

        Iterator<String> iterator = strings.iterator();
        while (iterator.hasNext()) {
            String value = iterator.next();
            strings.remove(value);
            System.out.println("Thread name " + Thread.currentThread().getName());
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        strings.forEach(v -> System.out.println(v));

    }
}

Я ожидаю, что внутренний поток не должен повторять объекты, которые удалены основным потоком. Поправь меня, если мое понимание неверно.

1 Ответ

4 голосов
/ 09 июня 2019

Да, вы не правы.Из документов :

Метод итератора в стиле «моментальный снимок» использует ссылку на состояние массива в момент создания итератора.Этот массив никогда не изменяется в течение времени жизни итератора, поэтому вмешательство невозможно, и итератор гарантированно не выдает исключение ConcurrentModificationException.

Таким образом, по замыслу итератор не изменится, когда другой поток внесет изменения.

...