【问题标题】:Removing an item from ArrayList in a separate Thread in Java在 Java 中的单独线程中从 ArrayList 中删除项目
【发布时间】:2013-05-26 18:30:59
【问题描述】:

我有一个长时间运行的循环。

在循环内部,我有另一个循环来迭代(使用迭代器)arrayList。

如果在遍历数组列表时满足条件,我将启动一个线程,同时将当前数组列表项和当前迭代器传递给它。

一些示例代码:

List<Test> testList = Collections.synchronizedList(new ArrayList<Test>());

//scanTests in a thread
while(scanTests) {
    for(Iterator<Test> itr = this.testList.iterator(); itr.hasNext();) {
        Test test = itr.next();
        if (test.closed == true && !test.inUpdateThread) {
            test.inUpdateThread = true;
            UpdateThread urt = new UpdateThread(test, itr);
            new Thread(urt).start();
        }
    }
}

//scanSomethingElse is in another thread
while (scanSomethingElse) {
    //manipulating testList 
}

如果在 UpdateThread 中满足条件,我想像这样从 testList 中删除该项目:

this.itr.remove();

我同时有另一个长时间运行的循环(在另一个单独的线程中),它在数组 List 上执行类似类型的处理(读取、写入等)。

我的问题是,如果在另一个循环中我正在迭代 testList,这会反映来自另一个循环的变化吗?

(如果你想知道为什么我使用线程进行同步,这是为了远程资源和数据库交互,我需要这个循环是恒定的和即时的,没有等待时间)。

【问题讨论】:

  • 我认为如果你在迭代时删除元素,你会得到一个 ConcurrentModificationException,见:docs.oracle.com/javase/6/docs/api/java/util/…
  • 没有。这是一个常见的错误。如果您使用迭代器中的 add()/remove() 方法,则可以在迭代时删除/添加。迭代器维护一个“modcount”(修改计数)属性,它在每次操作时更新该属性。如果修改 it.remove(),modcount 会增加。如果你 list.remove(),modcount 不会增加,因此在下一个 it.next() 时,你会得到这个异常。我认为这里的问题是迭代器本身不是线程安全的
  • @adenoyelle 如果该项目被另一个线程删除,它肯定不会通过 iterator.remove() 删除 - 所以会发生异常
  • 他正在将迭代器传递给线程。
  • @lcplussplus :你能澄清一下你对 UpdateThread 中的迭代器做了什么吗?恕我直言,在将迭代器传递给另一个可以更新它的线程时循环迭代器是一个严重的设计缺陷。

标签: java multithreading arraylist


【解决方案1】:

你为什么不使用类似的东西:

while (true) {
    for (int i = 0;i < testList.size(); i++) {
        Test test = testList.get(i);
        if (test.closed == true && !test.inUpdateThread) {
            test.inUpdateThread = true;
            UpdateThread urt = new UpdateThread(some other constructor here);
            new Thread(urt).start();
        }; 

    };
};

//UpdateThread类有一个构造函数UpdateThread(Test test, Iterator itr)。所以只需修改它以适应这个例子,或者发布它我认为 ki 可以为你做。

【讨论】:

  • 所以基本上我会打电话删除 testList.remove(test);在 UpdateThread 中而不是传递迭代器?
  • 是 testList.remove(test);例如将从列表中删除测试。
  • 我只想在迭代时删除当前的“测试”项,我只能在 UpdateThread 中确定是否要删除它。
  • 所以 UpdateThread 构造函数应该类似于 UpdateThread(Test test, List list) 这样您就可以从 UpdateThread 类中调用 list.remove(test)。
  • 我的印象是,对 arrayList 使用迭代器是在遍历它时删除项目的唯一方法。
猜你喜欢
  • 2023-03-15
  • 1970-01-01
  • 2012-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多