ConcurrencyException

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

Я получаю ConccurentModificationException в методе run(). Я попробовал следующее, и это не сработало:

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 ответа

Решение

Run() не находится в синхронизированном блоке, потому что он выполняется в другом потоке. Вы можете использовать synchronized в вашем методе run, но было бы намного проще использовать параллельную коллекцию, которая выдает эту ошибку. Например, ConcurrentHashMap.

Кстати, я бы не стал запускать поток каждый раз, так как это может быть дороже, чем просто перебирать коллекцию. Я хотел бы использовать пул потоков, или сделать это в текущем потоке.


Замените свой метод этим

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

Вы не синхронизированы remove() призыв к Map, Если несколько потоков пытаются позвонить run() в то же время, он бросит ConcurrentModificationException что является причиной в вашем случае.

Вам может потребоваться использовать синхронизированный при запуске () (или) использовать одновременный сбор, например ConcurrentHashMap

Другие вопросы по тегам