将是SimpleDateFormat.parse的错误

时间:2012-05-18 17:40:09

标签: 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.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");

}

经过多次测试,这是非常奇怪的。基本上,它永远不会完全完成,它会非常随机地发生异常。

你看到代码应该是正确的,但是:当i为500或i为799或i为988时,它会遇到异常(这里只举几个例子,意思是当i = 0时它没有发生,它实际上已经完成了一些圆圈),异常可能会在行日期date = dateFormat.parse(aDate, p);或行throw new RuntimeException("just a test");中抛出;

每个人都可以告诉我什么是错的吗?

3 个答案:

答案 0 :(得分:3)

SimpleDateFormat.parse()使用名为calendar的实例变量来构建字符串中的日期。如果两个线程同时尝试解析,calendar变量将被破坏,你将得到错误的结果。

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

使用SDF时还要考虑以下几点。

  1. 创建SimpleDateFormat是expensive。除非很少这样做,否则不要使用它。

  2. 好的,如果你能忍受一点阻塞。如果formatDate()使用不多,请使用。

  3. 最快的选项如果您重复使用线程(thread pool)。使用的内存多于2,并且启动开销较高。

  4. 对于应用程序,2和3都是可行的选择。哪种情况最适合您的情况取决于您的使用案例。注意过早优化。只有你认为这是一个问题才能做到。

    对于第三方使用的图书馆,我会使用选项3。

答案 1 :(得分:2)

你的代码只是简单的工作,即使在20次重播之后。因此,让我们猜测你的真正的 SSCCE可能是什么样的:

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的建议,他会为你报道。

答案 2 :(得分:0)

p.getIndex()!= aDate.length()

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