Я получаю ConcurrentModificationException
, когда запускаю второй таймер после отмены первого. Оба таймера используют отдельный ArrayList
и перебирают его. Никакого удаления/изменения в списке не производится, все равно выбрасывается ConcurrentModificationException
.
Это происходит, когда я останавливаю первый таймер и сразу запускаю второй. Если я подожду несколько секунд перед запуском второго таймера, то он работает нормально.
В итоге я сделал копию входящего списка на обоих таймерах, передав копию таймеру, но все равно получаю ошибку. Не уверен, почему, поскольку я перебираю список и просто читаю значения.
Код для таймера №1:
private void timerwork(final List<Object> list) throws IOException {
timer = new Timer();
final List<Object> taskList = list;
timer.scheduleAtFixedRate(new CustomTimerTask(taskList) {
@Override
public void run() {
if (taskList != null && !taskList.isEmpty()) {
synchronized (taskList) {
for (Object o: taskList) {
try {
// this method takes each object,
// does some logic and writes to a flat file,
// it does not modify the object itself,
// but just reads it and does some calculation
// on some local variables
valueIncrementOperation(o);
} catch (IOException e) {
timer.cancel();
timer.purge();
throw new RuntimeException(e.getMessage(), e);
}
}
//once exited out of the loop, it copies the flat file to another file
try {
copyFileUsingFileChannels(source, finaldest);
} catch (IOException ignore) {
}
}
}
public synchronized void valueIncrementOperation(Object o) throws IOException {
DataInputStream d = new DataInputStream(new FileInputStream(sourcefile));
DataOutputStream out = new DataOutputStream(new FileOutputStream(tempfile));
initialValue = Long.parseLong(o.getDefaullt_value());
String count;
String t;
while ((count = d.readLine()) != null) {
String u = count.toUpperCase();
String[] z = u.split(" ");
if (z[0].contains(o.getO())) {
// .............. *snip* ..............
out.writeBytes(t + "\n");
}
d.close();
out.close();
copyFileUsingFileChannels(source, initialDest);
}
Код CustomTimerTask:
public class CustomTimerTask extends TimerTask {
private List<Object> list = new ArrayList<Object>();
public CustomTimerTask(List<Object> list) {
this.list = list;
}
@Override
public void run() {
// TODO Auto-generated method stub
}
}
Таймер 2 имеет аналогичную логику: т. е. он копирует входящий список перед передачей на таймер 2.
Тем не менее я получаю эту ошибку:
Exception in thread "Timer-0" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
Обходной путь - подождать несколько секунд перед запуском timer2. Есть ли лучший способ справиться с этим сценарием?
this.list = list;
не создает копию списка, а просто создает новую ссылку на тот же список. - person David Conneely   schedule 29.11.2013final List<Object> taskList = list;
и передаюtaskList
в конструктор - person yonikawa   schedule 29.11.2013final List<Object> taskList = new ArrayList<Object>(list);
, чтобы сделать копию, или используйте реализацию копирования при записи, как упоминал @Gennaro. - person David Conneely   schedule 29.11.2013final List<Object> taskList = list;
на самом деле не делал копию, я полагаю...List<Object> taskList = new ArrayList<Object>(list);
-- это работает... Спасибо, братан... - person yonikawa   schedule 29.11.2013Vector
, он синхронизирован (обрабатывает параллельные операции) - person   schedule 29.11.2016