1

私は CopyOnWriteArrayList について学習していますが、私の理解では機能していません。私は 2 つのスレッドを持っています。1 つはメイン スレッドで、もう 1 つはめねじです。内部スレッドが 5 秒間スリープしている間に、メイン スレッドが CopyOnWriteArrayList コレクションからオブジェクトを削除しています。メインスレッドは、内部スレッドが反復するずっと前に削除操作を完了していますが、内部スレッドはまだ完全なコレクションを反復しています。つまり、メインスレッドによって削除されます。

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));

    }
}

メインスレッドによって削除されたオブジェクトを内部スレッドが反復すべきではないことを期待しています。私の理解が間違っている場合は修正してください。

4

1 に答える 1

4

はい、あなたは間違っています。ドキュメントから:

「スナップショット」スタイルの反復子メソッドは、反復子が作成された時点での配列の状態への参照を使用します。この配列は反復子の有効期間中に変更されることはないため、干渉は不可能であり、反復子は ConcurrentModificationException をスローしないことが保証されています。

したがって、設計上、他のスレッドが変更を加えてもイテレータは変更されません。

于 2019-06-09T14:12:45.653 に答える