伪代码如下。
public class MyObject
{
private List<Object> someStuff;
private Timer timer;
public MyObject()
{
someStuff = new ArrayList<Object>();
timer = new Timer(new TimerTask(){
public void run()
{
for(Object o : someStuff)
{
//do some more stuff involving add and removes possibly
}
}
}, 0, 60*1000);
}
public List<Object> getSomeStuff()
{
return this.someStuff;
}
}
所以本质上,问题是上面代码中未列出的其他对象调用 getSomeStuff() 来获取只读列表。发生这种情况时,我在计时器线程中收到 concurrentmodificationexception。我尝试使 getSomeStuff 方法同步,甚至尝试在计时器线程中使用同步块(synchronized block),但仍然不断出现错误。停止并发访问列表的最简单方法是什么?
最佳答案
在线程中迭代列表之前,您可以使用 java.util.concurrent.CopyOnWriteArrayList
或制作副本(或使用 Collection.toArray
方法获取数组) .
除此之外,在 for-each 构造中删除会破坏迭代器,因此在这种情况下它不是处理列表的有效方法。
但您可以执行以下操作:
for (Iterator<SomeClass> i = list.iterator(); i.hasNext();) {
SomeClass next = i.next();
if (need_to_remove){
i.remove(i);
}
}
或
for (int i = list.size() - 1; i >= 0; i--){
if (need_to_remove) {
list.remove(i);
}
}
另请注意,如果您的代码从不同线程访问列表并且列表被修改,您需要同步它。例如:
private final ReadWriteLock lock = new ReentrantReadWriteLock();
final Lock w = lock.writeLock();
w.lock();
try {
// modifications of the list
} finally {
w.unlock();
}
.................................
final Lock r = lock.readLock();
r.lock();
try {
// read-only operations on the list
// e.g. copy it to an array
} finally {
r.unlock();
}
// and iterate outside the lock
但请注意,带锁的操作应尽可能短。
关于java - 防止并发修改异常的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10218883/