Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
不建议调用静态java.text.DateFormat方法?_Java_Static - Fatal编程技术网

不建议调用静态java.text.DateFormat方法?

不建议调用静态java.text.DateFormat方法?,java,static,Java,Static,我收到一个查找bug错误-调用静态java.text.DateFormat方法 我不知道为什么在下面做这些事情不好/不可取 private static final Date TODAY = Calendar.getInstance().getTime(); private static final DateFormat yymmdd = new SimpleDateFormat("yyMMdd"); private String fileName = "file_" + yymmdd.fo

我收到一个查找bug错误-调用静态java.text.DateFormat方法 我不知道为什么在下面做这些事情不好/不可取

private static final Date TODAY = Calendar.getInstance().getTime();
private static final DateFormat yymmdd = new SimpleDateFormat("yyMMdd"); 

private String fileName = "file_" + yymmdd.format(TODAY);

首先,它不是线程安全的。

日期格式不是线程安全的,这意味着它们维护状态的内部表示。如果多个线程同时访问同一个实例,在静态上下文中使用它们可能会产生一些非常奇怪的错误

我的建议是将变量设置为使用它们的地方的局部变量,而不是将它们设置为类的静态属性。在初始化类时,您可能正在执行此操作,因此您可以在构造函数中执行此操作:

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);
    }
    ...
}
如果您需要在多个位置使用格式化程序,您可以在需要时将模式设置为静态最终模式,并创建一个新的本地
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
    }
}
该问题的答案是:

正如JavaDoc所述,日期格式是 对于多线程系统来说本质上是不安全的 使用。探测器找到了一个呼叫 DateFormat的一个实例,具有 通过一个静态场获得。这 看起来可疑

有关此功能的更多信息,请参见Sun 臭虫6231579和太阳虫6178997

报告建议:

日期格式不同步。信息技术 建议创建单独的 格式化每个线程的实例。如果 多线程访问一种格式 同时,它必须同步 外部

关于静态使用“TODAY”的语义也有一个很好的观点

顺便说一句,我实际上在高流量的生产环境中看到过这种情况,开始调试是一件非常令人困惑的事情;因此,根据我的经验,FindBugs警告实际上是一个有用的建议(与其他一些静态分析规则不同,这些规则有时似乎很挑剔)。

你确定不是吗

private static final DateFormat yymmdd = new SimpleDateFormat("yyMMdd"); 
??这就是错误消息所指示的


我认为它的目标是
DateFormat
不是线程安全的,因此将实例作为静态字段表示潜在的竞争条件。

我认为这是因为格式不是线程安全的

(我没有看到findbugs抱怨什么,你能提供
警告文本?

您可以通过在同步块中包装对DateFormat的所有引用来消除此问题-只需确保所有调用都包装在同一个同步对象中

我不确定FindBugs是否在抱怨这一点,但我看到您的代码存在一个问题,即您现在将
定义为类级(静态)、常量(最终)变量。这传达了您希望
今天
永不改变的意图(我不认为是这样,因为java.util.Dates是可变的,但这是另一回事)

考虑一下如果应用程序运行多天会发生什么
今天(除非更新)将引用应用程序启动的日期,而不是当前日期。你确定这就是你的意思吗

这可能根本不是代码中的一个bug,但目的并不明确,我相信这可能就是FindBugs所抱怨的。

有一个线程安全的对象。 但它只进行格式化,不进行解析

如果你能使用commons-lang,这可能会对你很有用

private static final Date TODAY = Calendar.getInstance().getTime();
private static final FastDateFormat yymmdd = FastDateFormat.getInstance("yyMMdd");

private String fileName = "file_" + yymmdd.format(TODAY);

另一种未提及的方法是使用ThreadLocal。有关3个选项之间的更多信息和性能比较,请参阅:

  • 每次创建一个实例
  • 同步存取
  • 使用ThreadLocal
使用ThreadLocal的示例:

private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
    @Override
    protected SimpleDateFormat initialValue() {
        return new SimpleDateFormat("yyMMdd");
    }
};

撇开调用方法不谈,这段代码看起来确实有点可疑-
今天将是一个固定的日子,格式化程序是最终的非静态的?而且今天可能并不总是“今天”,例如,如果加载这个类,然后让JVM运行到第二天-任何依赖今天作为当前日期的逻辑都不会工作,除非您要解释这种差异。@Peter-是的,每次运行都会重置程序。这可能会消除FindBugs错误,但在需要时只更新一个本地日期格式不是更符合逻辑吗?@Rob,我想这取决于同步是否真的可能会偶尔阻塞一次,或者只是为了安抚FindBugs的礼节。如果创建一个新的DateFormat的开销在某种程度上影响了系统性能,我想同步可能是一种替代方法,但我怀疑在大多数情况下它是否会影响系统性能。另外,如果是这样的话,它可能是一个负载更高的系统,我想同步也会以类似的方式阻碍性能。我不太确定,我认为每次调用myMethod()时创建SimpleDataFormat太贵了。@eradicus-你有性能指标证明它“太贵”吗?除非您已经注意到它是应用程序的瓶颈,否则我宁愿使用局部方法,而不是使用
static final
s来扰乱全局范围。强制性克努斯:为什么变量是“最终的”,即常量还不够?如果它不能更改,所有线程都应该能够共享它,不是吗?或者这是初始化的竞争条件问题?
final
只意味着不能重新分配引用-引用点所在对象的内容不能从存在
final
中得到任何保证。
DATE_FORMAT.get().format( TODAY )