我使用的對象,作爲一個包裝,它粗略用於在地圖字符串的一個:我不在線程安全?
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);
} ...
}
}
映射器當我訪問方法一次由幾個線程執行,一些行爲發生,這隻能通過併發訪問來解釋,例如可能有一個NumberFormatException
或一個ParseException
,其中解析的字符串是.430.430,而不是.430等等。
有兩個方面引起我的興趣: 1.)只能以只讀方式訪問包裝。雖然訪問收藏不同步,但我的印象是這應該始終有效。 2.)在第一次嘗試找到問題時,我更改了Wrapper
類的構造函數以執行formatNumber
方法(顯然是單線程的),該方法消除了執行中的所有異常。
有人可以解釋一下嗎?
編輯: Wrapper
類中的地圖填充在構造函數中,該構造函數絕大多數情況下都是單線程的。之後,包裝的設計使地圖是不可變的。
根據上述評論,請使用一個ThreadLocal <的NumberFormat> – Nate 2012-01-18 13:54:56
@Nate是的顯而易見的解決方案(並會在第一時間對我來說永遠使用'ThreadLocal' - !這給出了被異國情調的加分)。儘管取決於訪問頻率等等。爲每個線程創建一個新實例(如果僅使用一次)可能比某些鎖定效率低。 – Voo 2012-01-18 13:57:07
理解並接受。我沒有閱讀javadoc,但是我正在瀏覽NumberFormat(和子類)源代碼,並且沒有發現任何可以解釋爲什麼NumberFormat不是線程安全的成員變量。即使其成員變量是以只讀方式訪問的,類是不是線程安全的? – Jonathan 2012-01-18 14:06:55