首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ConcurrentModificationException TimerTask

ConcurrentModificationException TimerTask
EN

Stack Overflow用户
提问于 2013-11-29 17:59:19
回答 1查看 3.6K关注 0票数 3

当取消第一个定时器后启动第二个定时器时,我就会得到ConcurrentModificationException。两个计时器都使用单独的ArrayList并遍历它。没有在列表上执行删除/修改,仍然会抛出ConcurrentModificationException

当我停止第一个定时器并立即启动第二个定时器时,就会发生这种情况。如果我在启动第二次定时器之前等待几秒钟,那么它可以正常工作。

最后,我在两个计时器上创建了一个传入列表的副本,将副本传递给计时器,但我还是得到了错误。不知道为什么,因为我正在遍历列表,只读取值。

计时器#1的代码:

代码语言:javascript
复制
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代码:

代码语言:javascript
复制
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
    }
}

Timer 2具有类似的逻辑:即,它在传递到timer2之前复制传入的列表。

不过,我还是看到了这个错误:

代码语言:javascript
复制
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之前等待几秒钟。是否有更好的方法来解决这种情况?

EN

回答 1

Stack Overflow用户

发布于 2018-02-05 18:02:57

我们从堆栈跟踪中知道,异常是从ArrayList内部抛出的。因此,让我们来看看处理Lists的代码行。(为了便于阅读,删除了多余的代码)。

首先是方法调用:

代码语言:javascript
复制
private void timerwork(final List<Object> list) {
    final List<Object> taskList = list;

这意味着taskList,与传入的对象完全相同(称为list)。

其次,这个List被传递到CustomTimerTask的构造函数中。

代码语言:javascript
复制
timer.scheduleAtFixedRate(new CustomTimerTask(taskList) {

第三,让我们检查构造函数:

代码语言:javascript
复制
private List<Object> list = new ArrayList<Object>();
public CustomTimerTask(List<Object> list) {
    this.list = list;
}

因此,您的new ArrayList被丢弃,并被参数list替换,我们知道它是--与最初传递给timerwork()的完全相同的对象

我知道你说过:

最后我做了一份收到的名单

但这在你发布的任何代码中都没有看到。此外,我们也不知道(因为您还没有发布) timerwork()的调用代码,但可能是这样的:

代码语言:javascript
复制
List<Object> list = ....
timerwork(list);
timerwork2(list);

如果是这样的话,那么我们将看到两个计时器任务都在上操作--不同线程中的完全相同的对象,这将解释ConcurrentModificationException

CustomTimerTask的构造函数中,一个简单的修复和一个好的实践--即使我的诊断是不正确的--

代码语言:javascript
复制
private List<Object> list;
public CustomTimerTask(List<Object> list) {
    // CustomTimerTask gets its own copy to play with
    this.list = new ArrayList<Object>(list);
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20291241

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档