DateFormats不是線程安全的,這意味着它們保持狀態的內部表示。如果多個線程同時訪問同一個實例,在靜態環境中使用它們會產生一些非常奇怪的錯誤。
我的建議是將你的變量局部放在你使用它們的地方,而不是使它們成爲類的靜態屬性。它看起來就像你可能會做這個,當你初始化類,所以你可以做到這一點在構造函數:
public class MyClass {
private String fileName;
public MyClass() {
final Date today = Calendar.getInstance().getTime();
final DateFormat yymmdd = new SimpleDateFormat("yyMMdd");
this.fileName = "file_" + yymmdd.format(TODAY);
}
...
}
如果你需要使用在多個地方格式化,你可能只是使圖案static final
並在需要時創建新的本地DateFormat
:
public class MyClass {
private static final String FILENAME_DATE_PATTERN = "yyMMdd";
public void myMethod() {
final DateFormat format = new SimpleDateFormat(FILENAME_DATE_PATTERN);
// do some formatting
}
}
的FindBugs documentation的問題說:
正如Javadoc,是的DateFormats 固有不安全的多線程使用 。檢測器發現 的一個調用DateFormat的實例,該實例已通過靜態字段獲得 。這 看起來可疑。
欲瞭解更多信息,請參閱太陽 錯誤#6231579和太陽錯誤#6178997。
而且javadoc for DateFormat提示:
日期格式不同步。建議使用 爲每個線程創建單獨的 格式實例。如果多個線程同時訪問格式 ,則必須在外部同步 。
Jack Leow's answer對於「TODAY」的靜態使用的語義也有一個好的觀點。另外,我已經看到這種情況發生在高流量的生產環境中,首先要進行調試是一件非常令人困惑的事情;所以根據我的經驗,FindBugs警告實際上是一個有用的建議(與其他一些靜態分析規則不同,有時似乎太挑剔)。
除了調用方法,這段代碼確實看起來有點懷疑 - 「TODAY」將是一個不變的日子,格式化程序是最終的非靜態的? – Pool 2010-03-09 14:30:51
今天也不總是「今天」,如果例如這個類被加載,然後JVM被運行到第二天 - 任何依賴TODAY成爲當天的邏輯將不起作用,除非你是佔這種差異。 – Peter 2010-03-09 15:17:24
@彼得 - 是的,程序正在爲每次運行重置。 – Joset 2010-03-09 15:19:35