(См. ответ Роланда , который берет идеи здесь и конкретизирует их в более полный пример с некоторыми замечательными дополнительными сведениями.)
Поскольку это одновременная хэш-карта, вы можетесделайте следующее.Обратите внимание, что все итераторы CHM реализуют необязательные методы, включая remove()
, который вы хотите.См. CHM API docs , в котором говорится:
Этот класс, его представления и итераторы реализуют все необязательные методы интерфейсов Map
и Iterator
.
Этот код должен работать (я не знаю тип Key
в вашем CHM):
ConcurrentHashMap<K,Long> fileservers = ...;
for(Iterator<Map.Entry<K,Long>> fsIter = fileservers.entrySet().iterator(); fileservers.hasNext(); )
{
Map.Entry<K,Long> thisEntry = fsIter.next();
Long time = thisEntry.getValue();
if( time > fileserverTimeout )
fsIter.remove( server );
}
Но учтите, что в других местах могут быть условия гонки ... Вынеобходимо убедиться, что другие части кода, обращающиеся к карте, могут справиться с этим видом самопроизвольного удаления - т. е., вероятно, всякий раз, когда вы касаетесь fileservers.put()
, вам понадобится немного логики, включающей fileservers.putIfAbsent()
.Это решение с меньшей вероятностью создает узкие места, чем использование synchronized
, но оно также требует немного больше размышлений.
Где вы написали: «Если время сервера обновляется здесь, у меня возникла проблема», то именно там putIfAbsent()
входит. Если запись отсутствует, либо вы ее раньше не видели, либо вы недавно сбросили ее со стола.Если необходимо согласовать две стороны, вы можете вместо этого ввести блокируемую запись для записи и выполнить синхронизацию на этом уровне (т. Е. Синхронизировать запись при выполнении remove()
, а не навесь стол).Тогда конец вещей put()
также может синхронизироваться с одной и той же записью, исключая потенциальную расу.