5

次のような擬似コードを次に示します。

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 メソッドを同期させようとしましたが、タイマー スレッドで同期ブロックを試してみましたが、それでもエラーが発生し続けました。リストへの同時アクセスを停止する最も簡単な方法は何ですか?

4

2 に答える 2

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);                
    }
}

また

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 

ただし、ロックを伴う操作はできるだけ短くする必要があることに注意してください。

于 2012-04-18T22:20:50.880 に答える
4

のリストのコピーを作成する必要がありますgetSomeStuff()。このようにプライベート フィールドへの参照を公開すると、実質的にパブリックになるため、とにかくやりたいことではありません。

また、コピーを として、ImmutableListまたは少なくとも変更不可能なリストとして返すことを検討してください。

于 2012-04-18T22:23:26.360 に答える