1

使用下面的代码,我注意到有时日期格式不正确。更奇怪的是,有时 timeStamp 会有正确的日期,而 timeStampCopy 会有错误的日期,反之亦然。

   public static Timestamp method(String date, DateFormat dateFormat) throws Exception {           

        // date is always "2017-02-17"     

        // original
        GregorianCalendar gCal = new GregorianCalendar();
        gCal.setTime(dateFormat.parse(date));
        Timestamp timeStamp = new Timestamp(gCal.getTimeInMillis());

        // copy
        GregorianCalendar gCalCopy= new GregorianCalendar();
        gCalCopy.setTime(dateFormat.parse(date));
        Timestamp timeStampCopy = new Timestamp(gCalCopy.getTimeInMillis());

        if (!timeStamp.toString().contains("2017-02-17"))
            System.out.println(timeStamp.toString());   
        if (!timeStampCopy.toString().contains("2017-02-17"))
            System.out.println(timeStampCopy.toString());   

        return timeStamp;

    }

我不确定是什么原因造成的,但我尝试使用 Date 对象并遇到同样的问题。我认为这可能是一个解析问题,但由于它两次做同样的事情我不确定。

以下是我得到的一些值:

timeStamp is:       2017-02-17 00:00:00.0
timeStampCopy is:   1700-02-17 00:00:00.0
4

2 回答 2

3

你说你DateFormat在线程之间共享实例。

根据Javadoc

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

请注意,这指的是访问DateFormat实例的外部同步,而不是方法。如果实例没有其他用途,则制作该方法synchronized只会解决此问题DateFormat

您可以:

  • 使用实例显式同步所有代码DateFormat(值得@GuardedBy为变量添加注释,以记录您希望在使用之前持有锁);
  • 将变量类型更改为ThreadLocal<DateFormat>(并适当初始化共享变量),以确保每个线程都有自己的DateFormat.

后一种方法的争用较少,因为每个线程都可以独立于其他线程进行。这也意味着您不能意外地忽略同步。

但是,有更好的库来处理日期和时间,这些库是在事后考虑到DateFormat缺乏线程安全等问题而设计的。在 Java 8 中,有java.timeAPI;对于早期版本的 Java,有 Jodatime。

于 2017-02-17T22:18:02.683 回答
1
于 2017-02-18T18:13:24.187 回答