Java 将是SimpleDataFormat.parse的一个bug

Java 将是SimpleDataFormat.parse的一个bug,java,simpledateformat,Java,Simpledateformat,我有以下代码: SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); TimeZone tz2 = TimeZone.getTimeZone("GMT"); dateFormat.setTimeZone(tz2); String aDate = "2012-05-02 23:59:59"; for(int i=0 ; i<1000; i++){ dateFormat.setLe

我有以下代码:

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
TimeZone tz2 = TimeZone.getTimeZone("GMT");
dateFormat.setTimeZone(tz2);
String aDate = "2012-05-02 23:59:59";

for(int i=0 ; i<1000; i++){
        dateFormat.setLenient(false);
        ParsePosition p = new ParsePosition(0);
        Date date = dateFormat.parse(aDate, p);
        java.sql.Date sqlDate = null;
        if (p.getIndex() != aDate.length())
           throw new RuntimeException("just a test");

}
经过多次测试后,它变得非常奇怪。基本上,它永远不会完全完成,它会非常随机地出现异常

你看,代码应该是正确的,但是:当我是500,我是799,我是988时,它遇到了异常。这里举一些例子,这意味着当我=0时它没有发生,它实际上已经完成了一些循环,异常可能会在任一行Date=dateFormat.parseaDate,p中抛出;或者行抛出新的运行时异常只是一个测试

每个人都能告诉我出了什么问题吗?

SimpleDataFormat.parse使用一个名为calendar的实例变量从字符串中构建日期。如果两个线程同时尝试解析,日历变量将被删除,并且您将得到错误的结果

使变量非静态并不一定有帮助,因为两个线程可能仍然使用同一个控制器。更好的解决方案是在每次解析日期时创建一个新的DateFormat对象,或者使用线程本地存储。更好的是,使用具有线程安全解析器的

在使用SDF.

时也要考虑以下几点 创建SimpleDataFormat是一个非常简单的过程。除非很少使用,否则不要使用

好吧,如果你能忍受一点阻碍的话。如果formatDate使用不多,请使用

如果你重复使用线程,最快的选择。使用的内存多于2个。并且具有更高的启动开销

适用于两种应用程序2。三,。这些都是可行的选择。哪个最适合您的用例取决于您的用例。谨防过早优化。只有当你认为这是一个问题时才去做


对于将由第三方使用的库,我将使用选项3。

p.getIndex!=等长


此语句返回true,这意味着当您解析日期时,您没有使用整个字符串aDate,这意味着aDate也有时区或其他信息

即使在重新运行20次之后,您的代码也能正常工作。让我们来猜测一下你的真实SCSCE看起来是什么样子:

public static void main(String[] args) {
  final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
  dateFormat.setLenient(false);
  final String aDate = "2012-05-02 23:59:59";
  for (int i = 0; i < 2; i++)
    new Thread() { public void run() {
      for (int i = 0; i < 1000; i++) {
        ParsePosition p = new ParsePosition(0);
        dateFormat.parse(aDate, p);
        if (p.getIndex() != aDate.length())
          throw new RuntimeException("just a test");
      }
      System.out.println("Done");
    }}.start();
}

这或多或少与你描述的方式不同,原因很明显。请听@Bhavik Ambani的建议,他会为您讲述这一点。

请编写异常的完整堆栈跟踪。为了更快获得更好的帮助,请发布一条消息。经过多次测试后,垃圾无法编译,原因是if p.getIndex!=length抛出RuntimeException只是一个测试;让您的固定编译代码不间断地运行三分钟而不出错。也许你可以给我们看看真正不起作用的代码?抱歉,这是打字错误,已经修复,真正的代码可以编译和工作。但是你可以看到这里的aDate=2012-05-02 23:59:59,是一个绝对正确的日期字符串。好的,现在它可以工作了。不过,关于未使用的VAR有两个警告。您的意思只是第2条。适用。?从我的两项编号列表中,第二点适用,而第1点适用。你的代码不会编译。他是说,代码是有效的。它运行,没有例外。为了帮助您,我们需要查看引发异常的实际代码,而不是一个可以正常工作的简化示例。对不起,我不是说代码可以正常工作没有异常,它发生了上面内容中所述的异常,我是说代码已经编译并可以运行,这里的问题代码是由于打字错误。