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

tha*_*guy 5 java concurrency multithreading list 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

所以基本上问题是上面代码中未列出的其他对象调用getSomeStuff()来获取列表以用于只读目的.当发生这种情况时,我在计时器线程中得到concurrentmodificationexception.我尝试使getSomeStuff方法同步,甚至尝试在计时器线程中使用synchronized块,但仍然不断收到错误.停止并发访问列表的最简单方法是什么?

Eug*_*sky 14

在迭代线程中的列表之前,您可以使用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);                
    }
}
Run Code Online (Sandbox Code Playgroud)

要么

for (int i = list.size() - 1; i >= 0; i--){            
    if (need_to_remove) {
        list.remove(i);                
    }
}
Run Code Online (Sandbox Code Playgroud)

另请注意,如果您的代码从不同的线程访问列表并且修改了列表,则需要同步它.例如:

    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 
Run Code Online (Sandbox Code Playgroud)

但请注意,具有锁定的操作应尽可能短.