-4

次のコードがあります。

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");

}

何度もテストした後、それは非常に奇妙でした。基本的に、完全に終了することはなく、非常にランダムに例外が発生しました。

コードは正しいはずですが、おそらくi500 またはi799 またはi988 のときに例外が発生しました (ここでいくつか例を挙げてください。i= 0 のときに発生しなかったことを意味します。実際にはいくつかの円が終了しています)。date = dateFormat.parse(aDate, p);行Date または行のいずれかで例外がスローされる可能性がありますthrow new RuntimeException("just a test");

誰もが私に何が悪いのかアドバイスできますか?

4

3 に答える 3

3

SimpleDateFormat.parse()calendar文字列から日付を作成するために呼び出されるインスタンス変数を使用します。2 つのスレッドが同時に解析しようとすると、calendar変数が破壊され、間違った結果が得られます。

2 つのスレッドが同じコントローラーを使用している可能性があるため、変数を静的にしないことは必ずしも役に立ちません。より良い解決策は、日付を解析するたびに新しい DateFormat オブジェクトを作成するか、スレッド ローカル ストレージを使用することです。さらに良いことに、スレッドセーフなパーサーを備えたJodaTimeを使用してください。

SDF を使用する場合は、次の点にも注意してください。

  1. SimpleDateFormat の作成にはコストがかかります。めったに行わない限り、これを使用しないでください。

  2. 少しのブロックで生活できればOK。formatDate() をあまり使用しない場合に使用します。

  3. スレッドを再利用する場合の最速のオプション (スレッド プール)。2. より多くのメモリを使用し、起動のオーバーヘッドが高くなります。

アプリケーションの場合、2. と 3. の両方が実行可能なオプションです。どちらがあなたのケースに最適かは、ユースケースによって異なります。時期尚早の最適化に注意してください。これが問題であると思われる場合にのみ実行してください。

サードパーティが使用するライブラリの場合、オプション 3 を使用します。

于 2012-05-18T17:45:29.810 に答える
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 のアドバイスを聞いてください。彼はあなたのためにこれをカバーしています。

于 2012-05-18T17:54:26.487 に答える
0

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

このステートメントは true を返します。これは、日付を解析したときに、文字列 aDate の全体を消費しなかったことを意味します。つまり、aDate にはタイムゾーンまたはその他の情報も含まれていることを意味します。

于 2012-05-18T17:45:39.580 に答える