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所述,DateFormats本质上对于多线程使用是不安全的。检测器已找到对通过静态字段获得的DateFormat实例的调用。这看起来很可疑。
有关更多信息,请参见Sun Bug#6231579和Sun Bug#6178997。
而且DateFormat的javadoc建议:
日期格式不同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问一种格式,则必须在外部进行同步。
Jack Leow的答案也很好地说明了您静态使用“TODAY”的语义。
我不确定FindBugs是否对此抱怨,但是我在您的代码中看到的一个问题是您将其定义TODAY为类级别(静态),常量(最终)变量。这传达了您TODAY永远都不要改变的意图(我不相信这种情况,因为java.util.Dates是可变的,但这是另一回事了)。
考虑一下如果您的应用程序运行多天会发生什么?TODAY(除非您对其进行更新)将引用应用程序启动的日期,而不是当前日期。您确定这是您的意思吗?
这可能根本不是代码中的错误,但目的尚不清楚,我相信这可能是FindBugs抱怨的地方。
顺便说一句,我实际上已经在高流量的生产环境中看到了这种情况,一开始调试起来是一件非常令人困惑的事情。因此,以我的经验,FindBugs警告实际上是一个有用的建议(与其他一些静态分析规则不同,有时看起来有些挑剔)。



