forでlistを読み込み中に、別スレッドでlist addすると
exceptionが発生する
class ReadTask implements Runnable {
List<String> l;
ReadTask(List l) {
this.l = l;
}
@Override
public void run() {
try {
for (String str:this.l) {
System.out.println(str);
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
class WriteTask implements Runnable {
List<String> l;
WriteTask(List l) {
this.l = l;
}
@Override
public void run() {
for (int i=10; i<20; i++) {
l.add(String.valueOf(i));
System.out.println("added: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
public class Outer {
public static void main(String[] args) {
List<String> l = new ArrayList();
l.add("1");
l.add("2");
l.add("3");
ExecutorService es = Executors.newFixedThreadPool(3);
es.submit(new WriteTask(l));
es.submit(new ReadTask(l));
es.shutdown();
}
}
1
added: 10
2
added: 11
java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1043)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:997)
at com.mycompany.mavenproject1.ReadTask.run(Outer.java:21)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
added: 12
added: 13
added: 14
added: 15
added: 16
added: 17
added: 18
added: 19
CopyOnWriteArrayListに差し替えると、listのコピーを参照しに行く
結果exceptionが発生しない
コピーをとるタイミングはjvm次第?
List<String> l = new CopyOnWriteArrayList<>();
1
added: 10
2
added: 11
3
added: 12
10
added: 13
added: 14
added: 15
added: 16
added: 17
added: 18
added: 19