Ada*_*ski 3 java concurrency system-properties
以下片段开始抛出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)
}
Run Code Online (Sandbox Code Playgroud)
我正在运行一个多线程应用程序,不幸的是我无权访问正在修改系统属性的代码(它甚至可能是第三方库)。
为了解决这个问题,我们可以拍摄系统属性键的快照:
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!
}
Run Code Online (Sandbox Code Playgroud)
请注意value
注释 - 虽然stringPropertyNames
指出set of keys in this property list where the key and its corresponding value are strings
,但系统属性可能同时已更改。
何必做那么多跑腿的活呢?
系统属性是 的实例java.util.Properties
,并且它的方法getProperty
是setProperty
线程安全的。
不幸的是,属性的条目集的迭代器(我在问题中使用过)不是线程安全的:
如果在对集合进行迭代时修改了映射(除非通过迭代器自己的删除操作,或通过迭代器返回的映射条目上的 setValue 操作),则迭代的结果是未定义的
所以实际上当我迭代该映射时,某些系统属性被修改(=该条目所说的已修改),这导致 CME 被抛出。
此问答对也适用于任何通用Properties
用法 - 只是系统属性使其变得更加棘手,能够使用静态直接访问它们,例如java.lang.System.setProperty(String, String)
- 因此控制所有访问(特别是在共享代码中)变得更加困难。
归档时间: |
|
查看次数: |
3356 次 |
最近记录: |