Как я могу перебирать (системные) свойства потокобезопасным способом? - PullRequest
0 голосов
/ 21 сентября 2018

Следующая часть начинает генерировать ConcurrentModificationException в моем приложении (в итераторе):

final Map<?, ?> systemProperties = System.getProperties()
final Map<String, String> properties = (Map<String, String>) systemProperties

for (final Entry<String, String> entry : properties.entrySet()) { // exception here
    System.out.println(entry)
}

Я запускаю многопоточное приложение, и, к сожалению, у меня нет доступа к коду, которыйизменение системных свойств (это может быть даже сторонняя библиотека).

Ответы [ 2 ]

0 голосов
/ 22 сентября 2018

Вы можете заключить свои свойства в ConcurrentHashMap, чтобы любое из ваших составных действий, таких как итерация, навигация, проверка и действие и т. Д., Было поточно-ориентированным.например,

ConcurrentHashMap<String, String> props = new ConcurrentHashMap<>(
    (Map<String, String>)(Object)System.getProperties());

for(Map.Entry<String, String> entry: props.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

Обратите внимание, что итераторы, возвращаемые ConcurrentHashMap, еженедельно согласованы , что означает, что они могут отражать или не отражать изменения в коллекции после построения итератора.Если это не то, что вы хотели, вместо этого вы могли бы использовать Collections.synchronizedMap(), который платит некоторые штрафы в параллельном режиме.

0 голосов
/ 21 сентября 2018

Чтобы исправить это, мы можем взять снимок ключей системных свойств:

final Properties systemProperties = System.getProperties()
final Set<String> keys = systemProperties.stringPropertyNames()

for (final String key : keys) {
    System.out.println("key: " + key)
    final String value = systemProperties.getProperty(key)
    System.out.println("value: " + value) // value can be null!
}

Обратите внимание на комментарий value - пока stringPropertyNames сообщает set of keys in this property list where the key and its corresponding value are strings, системасвойство могло быть изменено за это время.


Почему так много работы?

Системные свойства являются экземпляром java.util.Properties, а его методы getProperty, setPropertyПотоково-безопасный.

К сожалению, итератор набора записей Properties (который я использовал в вопросе) не является поточно-ориентированным:

Если карта изменяется во время итерации поset выполняется (кроме как через собственную операцию удаления итератора или через операцию setValue для записи карты, возвращаемой итератором), результаты итерации не определены

Так что на самом деле, когда я перебирална этой карте было изменено какое-то системное свойство (= эта запись была изменена), что вызвало выброс CME.


Эта пара вопросов и ответов также применима к любому общему использованию Properties - только системные свойства делаютЭто сложнее, с возможностью доступа к ним напрямую с помощью статики, такой как java.lang.System.setProperty(String, String), поэтому управление всеми доступами (особенно в разделяемом коде) становится сложнее.

...