1

私のサーブレットでは、リクエストが来ると、日付オブジェクトを作成します。

Date now = new Date();

キャッシュ ルックアップを実行したいので、日付を次のようにフォーマットするヘルパー関数を作成する必要があります。

2012.04.24-10:34

つまり: yyyy-MM-dd,HH:mm

私は単純な日付形式を使用してこれを持っていました:

public class DateHelpers {
      public static final DateFormat minuteDateFormat = new SimpleDateFormat("yyyy-MM-dd,HH:mm", Locale.US);

      public static String getDateKey(Date now) {
         // use minuteDateFormat to format date
      }
}

しかし、単純な日付形式はスレッドセーフではないことを読んでいました。

文字列を日付形式に解析していないので、これを行うためのより優れた高速な方法があるでしょうか?

私は日付オブジェクトを取得して文字列にフォーマットしています。多くのリクエストがこの DateHelper 静的メソッドを使用して日付からキーを取得するため、スレッドセーフである必要があります。

4

7 に答える 7

5

一歩下がって、本当にパフォーマンスに追われている場合は、日付の書式設定をまったく避けて、キーに UNIX タイムスタンプを使用します (つまり、System.currentTimeMllis())。既存の日付オブジェクトに基づいて検索するdate.getTime()場合は、タイムスタンプが得られます。

分に丸めたい場合は、整数で割って 60,000 を掛けることができます。これは、はるかに高速で、スレッドセーフが保証されています。

日付をフォーマットする場合、通常は必要に応じて日付フォーマットを作成するか (それほど高価ではありません)、各ワーカーに明示的に関連付けるユーティリティ オブジェクトのプールを用意します。

スレッド ローカル ソリューションは機能しますが、時間の経過とともにすべての TL を追跡できなくなり、最終的にはデバッグがより困難なコードになってしまいます。

于 2012-04-24T14:58:53.023 に答える
4

を使用しThreadLocal<DateFormat>ます。

public class DateHelpers {
    private static final ThreadLocal<DateFormat> minuteDateFormat = new ThreadLocal<DateFormat>() {
        @Override protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd,HH:mm", Locale.US);
        }
    };

    public static String getDateKey(Date now) {
        DateFormat df = minuteDateFormat.get();
       // use df to format date
    }
}
于 2012-04-24T14:41:40.080 に答える
3

java.time

java.timeフレームワークは、Java 8 以降に組み込まれています。(チュートリアルを参照してください。)

スレッドセーフな新しい日付フォーマッタが含まれています: DateTimeFormatter.

もう 1 つの利点は、書式設定パターンでのオプション パーツのサポートです。

その作成は次のようになります。

protected static DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd,HH:mm");
于 2016-03-19T12:46:24.513 に答える
1

SimpleDateFormat の javadoc から:

スレッドごとに個別のフォーマット インスタンスを作成することをお勧めします。

あまりにも多くの開発者がそれを見ており、彼らの最初の本能は、ThreadLocal で同期するか、同期ブロックを追加することです。多くの場合、「予防措置」としてコードが ThreadLocal で埋め尽くされていますが、これは必要に迫られたわけではありません。トラブルシューティングが非常に困難になる可能性があります。代替手段がまったくない場合を除き、スレッド ローカルを使用してフォーマットを同期する理由はありません。本当に変更されない日付形式がある場合 (指定された文字列形式で static final とマークする理由)、本当に必要なのは、JVM で一度作成されたその日付形式のインスタンスです。アプリケーションの起動時に単純な日付形式を挿入するには、制御の反転を使用することをお勧めします。そうすれば、どこでも必要なときに、その存在を知ることができます。

于 2012-04-24T15:17:50.220 に答える
0

これで試してみてください

public class DateFormatTest {

  private static final ThreadLocal<DateFormat> df
                 = new ThreadLocal<DateFormat>(){
    @Override
    protected DateFormat initialValue() {
        return new SimpleDateFormat("yyyy-MM-dd,HH:mm", Locale.US);
    }
  };

  public Date convert(String source)
                     throws ParseException{
    Date d = df.get().parse(source);
    return d;
  }
}
于 2012-04-24T14:44:10.550 に答える
0

commons-lang のFastDateFormatはスレッドセーフです。さらに、ThreadLocal をサブクラス化して ClassLoader リークを作成しないでください。ただし、構文解析ではなく、書式設定のみを行います。

代替手段は、ステートレスでスレッドセーフなパーサーとフォーマッターを備えた優れたjoda-timeライブラリです。

于 2012-04-24T14:51:21.177 に答える
0

Joda time API からDateTimeFormatを試すこともできます。不変でスレッドセーフです。

于 2012-04-24T14:50:04.673 に答える