【发布时间】:2018-02-06 02:03:04
【问题描述】:
我在取消第一个计时器后启动第二个计时器时收到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 之前等待几秒钟。有没有更好的方法来解决这种情况?
【问题讨论】:
-
显而易见的问题:com.comcast.ams.simulator.service.OidTypesDao$2.run(OidTypesDao.java:307) 是什么? (显而易见的答案:您处于一个 foreach 循环中,您可以在其中从列表中删除项目。)
-
this.list = list;不会制作列表的副本,它只是对 same 列表进行新的引用。 -
一个简单的解决方案可能是将您的 List 替换为 java.util.concurrent.CopyOnWriteArrayList。这可能会解决您的问题。
-
@DavidC - 在调用定时器构造函数
final List<Object> taskList = list;并将taskList传递给构造函数之前,我正在复制列表 -
将其更改为
final List<Object> taskList = new ArrayList<Object>(list);以进行复制,或使用@Gennaro 提到的写时复制实现。
标签: java arraylist timer timertask concurrentmodification