необходимо предоставить поточно-реализацию следующего контейнера:Делегирования потокобезопасности к ConcurrentMap и AtomicInteger
public interface ParameterMetaData<ValueType> {
public String getName();
}
public interface Parameters {
public <M> M getValue(ParameterMetaData<M> pmd);
public <M> void put(ParameterMetaData<M> p, M value);
public int size();
}
Вещь метод размера должен вернуть точного количество paramters, содержащееся в настоящее время в экземпляре Parameters
. Итак, моя первая попытка была попытка делегировании потокобезопасности следующим образом:
public final class ConcurrentParameters implements Parameters{
private final ConcurrentMap<ParameterMetaData<?>, Object> parameters =
new ConcurrentHashMap<>();
//Should represent the ACCURATE size of the internal map
private final AtomicInteger size = new AtomicInteger();
@Override
public <M> M getValue(ParameterMetaData<M> pmd) {
@SuppressWarnings("unchecked")
M value = (M) parameters.get(pmd);
return value;
}
@Override
public <M> void put(ParameterMetaData<M> p, M value){
if(value == null)
return;
//The problem is in the code below
M previous = (M) parameters.putIfAbsent(p, value);
if(previous != null)
//throw an exception indicating that the parameter already exists
size.incrementAndGet();
}
@Override
public int size() {
return size.intValue();
}
Проблема заключается в том, что я не могу просто назвать parameters.size()
на экземпляре ConcurrentHashMap
вернуть фактический размер, как операция выполняет обход без и нет гарантии, что он будет получать фактический размер. В моем случае это неприемлемо. Итак, я решил сохранить поле, содержащее размер.
ВОПРОС: Можно ли каким-то образом делегировать безопасность потока и сохранить invariatns?
Без внешней блокировки вы не можете получить более высокую точность, чем ConcurrentHashMap уже предоставляет, так как вы не можете гарантировать атомические операции. – Ferrybig