Я хочу периодически перебрать ConcurrentHashMap
при удалении записей, например:перебрать ConcurrentHashMap во время удаления записей
for (Iterator<Entry<Integer, Integer>> iter = map.entrySet().iterator(); iter.hasNext();) {
Entry<Integer, Integer> entry = iter.next();
// do something
iter.remove();
}
Проблема заключается в том, что другой поток может обновлять или изменять значения, пока я итерация. Если это произойдет, эти обновления могут быть потеряны навсегда, потому что мой поток видит только устаревшие значения во время итерации, но remove()
удалит живую запись.
После некоторых раздумий, я придумал этот обходной путь:
map.forEach((key, value) -> {
// delete if value is up to date, otherwise leave for next round
if (map.remove(key, value)) {
// do something
}
});
Одна проблема состоит в том, что она не будет ловить изменения в изменяемых значений, которые не реализуют equals()
(например, AtomicInteger
). Есть ли лучший способ безопасного удаления с одновременными изменениями?
Почему бы не удалить запись перед выполнением каких-либо работ. –
@ClaudioCorsi, который не изменит тот факт, что я вижу устаревшую версию удаленной записи. – shmosel
Проблема в том, что вам нужно знать, что было обновлено с тех пор, как вы начали выполнять итерацию по карте. Даже если вы можете узнать, какие объекты были обновлены. По-прежнему возможно, что другой поток имеет ссылку на объект, который был обработан, но этот объект не был обновлен. Будет ли этот объект добавлен обратно или он просто обновляется? Должен ли этот объект генерировать другой обратный вызов? –