3

最近の質問で説明されているものと非常によく似たパターンを使用して、マルチスレッド アプリケーションの場合、奇妙な日付値を取得しています (たとえば、2025 年や 2035 年など、ソース データにそのような値が明らかに存在しない場合)。同時実行の問題が発生しているようです。

ソースコードは次のようになります

// Various Java DateFormat patterns, e.g. "yyyy-MM-dd".
private static final String[] DATE_PATTERNS = new String[] {...};

private static SimpleDateFormat[] getFormats(final String[] patterns)
{
    ThreadLocal<SimpleDateFormat[]> LOCAL_FORMATS = new ThreadLocal<SimpleDateFormat[]>()
    {
        @Override
        protected SimpleDateFormat[] initialValue()
        {
            List<SimpleDateFormat> formatList = new ArrayList<SimpleDateFormat>();

            for (String pattern:patterns)
            {
                formatList.add(new SimpleDateFormat(pattern));
            }

            return formatList.toArray(new SimpleDateFormat[formatList.size()]);
        }
    };

    return LOCAL_FORMATS.get(); // Create a thread-local copy
}

private static final SimpleDateFormat[] DATE_FORMATS = getFormats(DATE_PATTERNS);

静的な初期化の後、DATE_FORMATS配列は多数のクラスによってアクセスされます。これらのクラスはSimpleDateFormat、配列のオブジェクトを使用して、いくつかの日付文字列を解析またはフォーマットします。

特に を使用する場合、このような使用シナリオで同時実行性の問題が発生する可能性はありThreadLocalますか?

4

2 に答える 2

4

はい、同時実行の問題が発生する可能性があります。スレッド ローカル変数は何の役にも立ちません。クラスが初期化されたときにのみ使用され、すぐに取得されて静的定数に格納される日付形式の配列を一時的に格納します。

以降、すべてのスレッドは、スレッド ローカル変数から取得することなく、常に日付形式の同じインスタンスを同時に使用します。

コードは次のようにする必要があります。

private static final String[] DATE_PATTERNS = new String[] {...};
private static final ThreadLocal<SimpleDateFormat[]> DATE_FORMATS = 
    new ThreadLocal<SimpleDateFormat[]>() {
        @Override
        protected SimpleDateFormat[] initialValue() {
            List<SimpleDateFormat> formatList = new ArrayList<SimpleDateFormat>();

            for (String pattern : DATE_PATTERNS)
            {
                formatList.add(new SimpleDateFormat(pattern));
            }

            return formatList.toArray(new SimpleDateFormat[formatList.size()]);
        }
    };

public static SimpleDateFormat[] getDateFormats() {
    return DATE_FORMATS.get();
}

List<SimpleDateFormat>安全のために、配列ではなく変更不可能なものも使用します。

于 2012-07-07T16:03:49.257 に答える
2
// Various Java DateFormat patterns, e.g. "yyyy-mm-dd".

「mm」は月ではなく分であるため、「yyyy-mm-dd」という形式はおかしな結果になる可能性があります。javadoc から:

M   Month in year   Month   July; Jul; 07
...
m   Minute in hour  Number  30
于 2012-07-07T15:56:43.563 に答える