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