Java ConcurrentModificationException TimerTask
在取消第一个计时器后启动第二个计时器时,我会得到Java ConcurrentModificationException TimerTask,java,arraylist,timer,timertask,concurrentmodification,Java,Arraylist,Timer,Timertask,Concurrentmodification,在取消第一个计时器后启动第二个计时器时,我会得到ConcurrentModificationException。两个计时器都使用一个单独的ArrayList并对其进行迭代。没有对列表执行删除/修改,仍然会抛出ConcurrentModificationException 当我停止第一个计时器并立即启动第二个计时器时,就会发生这种情况。如果我在启动第二个计时器之前等待几秒钟,那么它工作正常 我最终在两个计时器上复制了一份传入列表,并将副本传递给计时器,但我仍然得到了错误。我不知道为什么,因为我正在
ConcurrentModificationException
。两个计时器都使用一个单独的ArrayList
并对其进行迭代。没有对列表执行删除/修改,仍然会抛出ConcurrentModificationException
当我停止第一个计时器并立即启动第二个计时器时,就会发生这种情况。如果我在启动第二个计时器之前等待几秒钟,那么它工作正常
我最终在两个计时器上复制了一份传入列表,并将副本传递给计时器,但我仍然得到了错误。我不知道为什么,因为我正在遍历列表,只读取值
计时器#1的代码:
解决方法是在启动计时器2之前等待几秒钟。有没有更好的方法来解决这个问题?我们从stacktrace知道异常是从
数组列表中抛出的。让我们来看看处理代码< >清单>代码>的代码行。(为了便于阅读,删除了多余的代码)
首先是方法调用:
private void timerwork(final List<Object> list) {
final List<Object> taskList = list;
第三,让我们检查该构造函数:
private List<Object> list = new ArrayList<Object>();
public CustomTimerTask(List<Object> list) {
this.list = list;
}
如果是这样的话,那么我们可以看到两个计时器任务都在不同线程中的完全相同的对象上运行,这可以解释ConcurrentModificationException
在CustomTimerTask
的构造函数中,一个简单的修复和一个良好的实践(即使我的诊断不正确):
private List<Object> list;
public CustomTimerTask(List<Object> list) {
// CustomTimerTask gets its own copy to play with
this.list = new ArrayList<Object>(list);
}
私有列表;
公共CustomTimerTask(列表){
//CustomTimerTask有自己的副本可供使用
this.list=新的ArrayList(列表);
}
显而易见的问题:com.comcast.ams.simulator.service.OidTypesDao$2.run(OidTypesDao.java:307)上有什么内容?(显而易见的答案是:您处于foreach循环中,从列表中删除项目。)this.list=list
不复制列表,它只是对同一列表进行新引用。一个简单的解决方案可能是用java.util.concurrent.CopyOnWriteArrayList替换列表。这可能会解决您的问题。@DavidC-我正在复制列表,甚至在调用计时器构造函数final list taskList=list编码>并将taskList
传递给构造函数或将其更改为final List taskList=new ArrayList(List)
来制作副本,或者使用@Gennaro提到的写时拷贝实现。
private void timerwork(final List<Object> list) {
final List<Object> taskList = list;
timer.scheduleAtFixedRate(new CustomTimerTask(taskList) {
private List<Object> list = new ArrayList<Object>();
public CustomTimerTask(List<Object> list) {
this.list = list;
}
List<Object> list = ....
timerwork(list);
timerwork2(list);
private List<Object> list;
public CustomTimerTask(List<Object> list) {
// CustomTimerTask gets its own copy to play with
this.list = new ArrayList<Object>(list);
}