With this code:
public class SynchroApp {
public static void main(String[] args) {
final List<String> unsyList = new ArrayList<>();
final List<String> syList = Collections.synchronizedList(unsyList);
TimerTask changeList = new TimerTask() {
boolean addElem = false;
@Override
public void run() {
// add / remove elements to keep size between 2 and 9
if (syList.size() < 2)
addElem = true;
else if (syList.size() > 8)
addElem = false;
if (addElem)
syList.add(String.valueOf(System.currentTimeMillis()));
else
syList.remove(0);
}
};
TimerTask reverseList = new TimerTask() {
@Override
public void run() {
try {
for (String s : syList)
s = new StringBuffer(s).reverse().toString();
} catch (Exception e) {
System.out.println("Exception: " + e);
}
}
};
new Timer().scheduleAtFixedRate(changeList, 0L, 30L);
new Timer().scheduleAtFixedRate(reverseList, 0L, 20L);
}
}
Why do I still receive some ConcurrentModificationException
on Iterator.next
?
EDIT: the update of the list elements in reverseList
wasn't working (as explained in comments). This code should work as expected:
for (int i = 0; i < syList.size(); i++)
syList.set(i, new StringBuffer(syList.get(i)).reverse().toString());
Even most synchronized collections do not like modifications and iterator together. From the API description of Collections.synchronizedList:
It is imperative that the user manually synchronize on the returned list when iterating over it:
List list = Collections.synchronizedList(new ArrayList()); ... synchronized (list) { Iterator i = list.iterator(); // Must be in synchronized block while (i.hasNext()) foo(i.next()); }
Also: You can use the collections from java.concurrent instead. They usually have a more refined synchronization approach.