Таким образом, в настоящее время решения, которое я имею в виду, чтобы иметь HashMap с несколькими читателями и после истечения срока его действия, демон нить будет получать данные из источника данных и создать новую карту, и как только его сделали возьмет заблокируйте старую HashMap, а затем скопируйте вновь созданную карту на старую.
Звучит правильно. Если, как вы подразумеваете в своем сообщении, никто не , изменяя HashMap после того, как он был создан, вы можете безопасно использовать его с несколькими потоками, если вы делите его правильно. Чтобы обеспечить неизменность, вы должны обернуть карту, используя Collection.unmodifiableMap(map)
.
Чтобы поделиться картой с потоками, вам нужно будет сделать это поле volatile, доступное всем потокам. Что-то вроде:
protected volatile HashMap map = null;
С ним быть volatile
, то вам не нужно делать какие-либо блокировки.You метод обновления, то выглядит следующим образом:
// no need to have synchronized here
HashMap updateMap(HashMap newMap) {
HashMap oldMap = this.map;
this.map = Collection.unmodifiableMap(newMap);
return oldMap;
}
Ни один из ваших методов не должны быть synchronized
, а также. volatile
поля будут намного лучше, потому что потоки будут пересекаться только с защитой памяти чтения, когда они получат доступ к общей карте и только барьер памяти записи при ее обновлении. С ключевым словом synchronized
потоки каждый раз пересекают барьер чтения и записи. Хуже того, ключевое слово synchronized
имеет блокировку накладных расходов, которая защищает мьютекс, который вам не нужен.
Будет ли копирование данных на новую карту занимать больше времени?
Копирование данных на новую карту потребует времени, но не более, чем типичное копирование данных между HashMaps. То, что равно, отличается тем, что доступ к полям volatile
может быть намного медленнее, чем прямой доступ к полю из-за пересекающихся барьеров памяти.
См. Http://stackoverflow.com/questions/104184/is-it-safe-to-get-values-from-a-java-util-hashmap-from-multiple-threads-no-modi. – gsl