Java日時APIシリーズ4-----Jdk 7および以前の日時クラスのスレッドセキュリティ問題

4550 ワード

1.Dateクラスは可変で、マルチスレッド同時環境ではスレッドセキュリティの問題が発生します.
(1)同時問題を処理するためにロックを使用することができる.
(2)JDK 8の使用  代わりにInstantまたはLocalDateTimeを使用します.
2.Calendarのサブクラスは可変であり、マルチスレッド同時環境ではスレッドセキュリティの問題がある.
(1)同時問題を処理するためにロックを使用することができる.
(2)JDK 8の使用  LocalDateTime 代替.
3.DateFormatとSimpleDateFormatはスレッドセキュリティの原因ではありません
(1)DateFormatではcalendarが共有変数であり,そのサブクラスSimpleDateFormatでも共有変数である.
DateFormatソース:
public abstract class DateFormat extends Format {
/** * The {@link Calendar} instance used for calculating the date-time fields * and the instant of time. This field is used for both formatting and * parsing. * * Subclasses should initialize this field to a {@link Calendar} * appropriate for the {@link Locale} associated with this * DateFormat . * @serial */protected Calendar calendar;
(2)SimpleDateFormatメソッドソース:
    private StringBuffer format(Date date, StringBuffer toAppendTo,
                                FieldDelegate delegate) {
        // Convert input date to time field list
        calendar.setTime(date);

        boolean useDateFormatSymbols = useDateFormatSymbols();

        for (int i = 0; i < compiledPattern.length; ) {
            int tag = compiledPattern[i] >>> 8;
            int count = compiledPattern[i++] & 0xff;
            if (count == 255) {
                count = compiledPattern[i++] << 16;
                count |= compiledPattern[i++];
            }

            switch (tag) {
            case TAG_QUOTE_ASCII_CHAR:
                toAppendTo.append((char)count);
                break;

            case TAG_QUOTE_CHARS:
                toAppendTo.append(compiledPattern, i, count);
                i += count;
                break;

            default:
                subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
                break;
            }
        }
        return toAppendTo;
    }

複数のスレッドが同じSimpleDateFormatオブジェクト(staticで修飾されたSimpleDateFormatなど)を同時に使用してformatメソッドを呼び出すと、複数のスレッドがcalendar.settimeメソッドを同時に呼び出すため、1つのスレッドがtime値を設定したばかりで、別のスレッドがすぐに設定したtime値を変更したため、返されるフォーマット時間が間違っている可能性があります.
4.SimpleDateFormatスレッドを安全に使用します.
(1)ThreadLocalによるstatic処理方法
    public static final ThreadLocal df = new ThreadLocal() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };
System.out.println(df.get().format(new Date()));
2019-12-14

(2)JDK 8の使用  DateTimeFormatter 代替.
 
参照先:https://www.cnblogs.com/wupeixuan/p/11511915.html?utm_source=gold_browser_extension
『アリババJava開発マニュアル』