A version of the static method append()
below, is sometimes called simultaneously by various threads:
public class CMEDemo {
private static final Logger LOG = Logger.getLogger(CMEDemo.class.getName());
private static final String[] SOME_DEMO = {"albino", "mosquito", "libido"};
private static final Set<String> SET_SOURCE = new LinkedHashSet<>(Arrays.asList(SOME_DEMO));
public static void append() {
//ConcurrentModificationException is thrown in the constructor for modifiableCopy.
LinkedHashSet<String> modifiableCopy = new LinkedHashSet<>(getBuiltInFunctions());
//Exception is not thown here, or later.
Set<String> doomed = modifiableCopy.stream()
.filter(f -> f.contains("quit")).collect(Collectors.toSet());
for (String found : doomed) {
LOG.log(Level.INFO, found);
}
}
public static Set<String> getBuiltInFunctions() {
return Collections.unmodifiableSet(SET_SOURCE);
}
}
Normally, all works as expected, but sometimes the LinkedHashSet constructor throws a ConcurrentModificationException:
java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:719)
at java.util.LinkedHashMap$LinkedKeyIterator.next(LinkedHashMap.java:742)
at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1042)
at java.util.AbstractCollection.addAll(AbstractCollection.java:343)
at java.util.LinkedHashSet.<init>(LinkedHashSet.java:169)
My JVM is Java 1.8_212. If I setup a test case to spawn multiple threads and let it run for a while, append() eventually throws ConcurrentModificationException. Why is this exception thrown, and how do I safely get a LinkedHashSet?