我正在使用一个对象,它大致用作字符串映射的包装器:
public class Wrapper {
private Map<String, String> values;
private Formatter formatter;
public BigDecimal getSpecialValue() {
String result = values.get("Special");
return formatter.formatNumber(result);
}
}
上述格式化程序大致用作 SimpleDateFormat 的映射器
public class Formatter {
private static final NumberFormat NUMBER_FORMAT;
public BigDecimal formatNumber(String s) {
Number num = NUMBER_FORMAT.parse(s);
if (num instanceof Integer) {
return new BigDecimal((Integer) num);
} else if (num instanceof Double) {
return new BigDecimal((Double) num);
} ...
}
}
当我同时通过多个线程访问 getSpecialValue()
方法时,会出现一些行为,这只能通过并发访问来解释,例如可能会出现 NumberFormatException
或 ParseException
,其中解析的字符串是 .430.430 而不是 .430 等等。
有两个方面引起了我的兴趣:
1.) 包装器只能以只读方式访问。尽管对集合的访问不是同步的,但我的印象是这应该始终有效。
2.) 在第一次尝试发现问题时,我更改了 Wrapper
类的构造函数以执行 formatNumber
方法(显然是单线程),这消除了所有异常下执行。
谁能解释一下?
编辑:
Wrapper
类中的映射被填充到构造函数中,这通常发生在单线程中。之后包装器被设计成 map 是不可变的。
最佳答案
只需在 jdoc 中搜索“thread”,就会发现 NumberFormat 类的以下内容:数字格式通常不同步。建议为每个线程创建单独的格式实例。如果多个线程并发访问一个格式,则必须在外部进行同步。
关于java - 我哪里不是线程安全的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8911128/