DateFormat 不是线程安全的,这意味着它们维护状态的内部表示形式。在静态上下文中使用它们可能会产生一些非常奇怪的错误,如果多个线程同时访问同一实例。
我的建议是使变量成为你使用它们的位置的局部变量,而不是使它们成为类的静态属性。看起来在初始化类时可能会执行此操作,因此您可以在构造函数中执行此操作:
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 文档说:
正如JavaDoc所述,DateFormat对于多线程使用本质上是不安全的。检测器发现了对 DateFormat 实例的调用,该调用是通过静态字段获得的。这看起来很可疑。
有关这方面的更多信息,请参阅 Sun Bug #6231579 和 Sun Bug #6178997。
DateFormat的javadoc建议:
日期格式不同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问一种格式,则必须在外部同步该格式。
Jack Leow的答案对你静态使用“TODAY”的语义也有一个很好的观点。
顺便说一句,我实际上已经在高流量生产环境中看到了这种情况,起初调试是一件非常令人困惑的事情。因此,根据我的经验,FindBugs警告实际上是一个有用的建议(与其他一些静态分析规则不同,这些规则有时似乎很挑剔)。