【发布时间】: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