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