ConcurrencyException

时间:2013-01-02 15:51:54

标签: java concurrency synchronized concurrentmodification synchronized-block

private static HashMap<String, FileInfo> sFileInfoObjectList = new CacheLinkedHashMap<String, FileInfo>();

public static synchronized FileInfo getFileInfoForProvider(...) {
 FileInfo foundFileInfo = null;

 (...)

 foundFileInfo = sFileInfoObjectList.get(hashEntryKey);

 (...)

 sFileInfoObjectList.put(hashEntryKey, foundFileInfo);

 (...)
}

public static synchronized void removeFileInfoForProvider(final int providerId) {
    Thread thread = new Thread() {
        @Override
        public void run() {
            Iterator<Entry<String, FileInfo>> it = sFileInfoObjectList.entrySet().iterator();
            while (it.hasNext()) {
                Entry<String, FileInfo> pair = it.next();
                FileInfo info = pair.getValue();
                if (providerId == info.mProvider) {                            
                    it.remove();
                }
            }
        }
    };
}

我在run()方法中遇到ConccurentModificationException。我试过跟随它并没有用:

public void run() {
    synchronized(sFileInfoObjectList) {
        Iterator<Entry<String, FileInfo>> it = sFileInfoObjectList.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, FileInfo> pair = it.next();
            FileInfo info = pair.getValue();
            if (providerId == info.mProvider) {                            
                it.remove();
            }
        }
    }
}

2 个答案:

答案 0 :(得分:2)

run()不在同步块中,因为它在另一个线程上运行。您可以在run方法中使用synchronized,但使用会引发此错误的并发集合会更简单。例如。的ConcurrentHashMap。

BTW:我不会每次都启动一个线程,因为它可能比迭代集合更昂贵。我会使用线程池,或者在当前线程中执行它。


用此

替换您的方法
public static void removeFileInfoForProvider(final int providerId) {
    Thread thread = new Thread() {
        @Override
        public void run() {
            removeFileInfoForProvider0(providerId);
        }
    };
    thread.start();
}

static synchronized void removeFileInfoForProvider0(final int providerId) {
    Iterator<Entry<String, FileInfo>> it = sFileInfoObjectList.entrySet().iterator();
    while (it.hasNext()) {
        Entry<String, FileInfo> pair = it.next();
        FileInfo info = pair.getValue();
        if (providerId == info.mProvider) {                            
            it.remove();
        }
    }
}

答案 1 :(得分:0)

您尚未同步remove() Map。如果多个线程尝试同时调用run(),则会抛出ConcurrentModificationException,这就是您的理由。

您可能需要使用synchronized on run()(或)使用并发集合,如ConcurrentHashMap