java - 防止并发修改异常的最佳方法

标签 java multithreading list concurrency concurrentmodification

伪代码如下。

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/

相关文章:

java - 将 Comparable 从 Comparator 转换为 Comparator?

java - HSQL 和 DBUnit - 给定架构 'SA' 不存在

c++ - OpenMP C++ 中的线程

java - 将 Spring @Async 放置在方法调用堆栈中的位置

r - 迭代地将新列添加到数据框列表中

python - 从文件中读取特定值并将它们存储在列表 python 中

java - 抽象方法必须在类或接口(interface)中定义吗?

java - -Djava.library.path 问题

python - 我想停止线程时不停止

c# - 如果删除元素,List<T> 会缩小大小