Я ищу способ отслеживать количество попыток одной и той же ключевой вставки в Map
в многопотоковой среде, так что Map
может быть чтение и обновление несколькими потоками одновременно. Если отслеживание попыток дублирования ключевых вставок невозможно достичь, альтернативным решением было бы убить приложение при первом знаке попытки повторной вставки ключа.Сохранение дорожки дублированных вставок на карте (многопоточная среда)
Следующий пользовательский синглтон Spring bean показывает глобальный кеш, используемый моим приложением, который загружается с использованием нескольких распределенных заданий весовой партии (одно задание для каждого загружаемого DataType
). Метод addResultForDataType
может быть вызван несколькими потоками одновременно.
public class JobResults {
private Map<DataType, Map<String, Object>> results;
public JobResults() {
results = new ConcurrentHashMap<DataType, Map<String, Object>>();
}
public void addResultForDataType(DataType dataType, String uniqueId, Object result) {
Map<String, Object> dataTypeMap = results.get(dataType);
if (dataTypeMap == null) {
synchronized (dataType) {
dataTypeMap = results.get(dataType);
if (dataTypeMap == null) {
dataTypeMap = new ConcurrentHashMap<String, Object>();
results.put(dataType, dataTypeMap);
}
}
}
dataTypeMap.put(uniqueId, result);
}
public Map<String, Object> getResultForDataType(DataType dataType) {
return results.get(dataType);
}
}
Здесь:
DataType
можно рассматривать как имя таблицы или имя файла из , где данные загружаются. Каждый DataType указывает одну таблицу или файл.uniqueId
представляет первичный ключ для каждой записи в таблице или файле.result
- объект, представляющий всю строку.- Вышеуказанный метод вызывается один раз за запись. В любой момент времени несколько потоков могут вставлять запись для одного и того же
DataType
или другогоDataType
.
Я думал о создании другой карты, чтобы сохранить трек из дублирующих вставок:
public class JobResults {
private Map<DataType, Map<String, Object>> results;
private Map<DataType, ConcurrentHashMap<String, Integer>> duplicates;
public JobResults() {
results = new ConcurrentHashMap<DataType, Map<String, Object>>();
duplicates = new ConcurrentHashMap<DataType, ConcurrentHashMap<String, Integer>>();
}
public void addResultForDataType(DataType dataType, String uniqueId, Object result) {
Map<String, Object> dataTypeMap = results.get(dataType);
ConcurrentHashMap<String,Integer> duplicateCount = duplicates.get(dataType);
if (dataTypeMap == null) {
synchronized (dataType) {
dataTypeMap = results.get(dataType);
if (dataTypeMap == null) {
dataTypeMap = new ConcurrentHashMap<String, Object>();
duplicateCount = new ConcurrentHashMap<String, Integer>();
results.put(dataType, dataTypeMap);
duplicates.put(dataType, duplicateCount);
}
}
}
duplicateCount.putIfAbsent(uniqueId, 0);
duplicateCount.put(uniqueId, duplicateCount.get(uniqueId)+1);//keep track of duplicate rows
dataTypeMap.put(uniqueId, result);
}
public Map<String, Object> getResultForDataType(DataType dataType) {
return results.get(dataType);
}
}
Я понимаю, что statemet duplicateCount.put(uniqueId, duplicateCount.get(uniqueId)+1);
не неявно поточно. Чтобы сделать его потокобезопасным, мне нужно будет использовать синхронизацию, которая замедлит мои вставки. Как я могу отслеживать дубликаты вставок, не влияя на производительность моего приложения. Если отслеживать повторяющиеся вставки нелегко, мне было бы хорошо сбрасывать исключение при первом признаке попытки перезаписать существующую запись на карте.
Примечание Я знаю, что Map
не позволяет дублировать ключи. Я хочу, чтобы отслеживать любые попытки и останавливать приложение, а не перезаписывать записи в Map
.
вы хотите, чтобы избежать дубликатов на внешней или внутренней 'Map' – Actorclavilis
@Actorclavilis Только внешняя карта. (См. Мою попытку решения). – Ping