Java日期時間API系列4-----Jdk7及之前的日期時間類的線程安全問題

1.Date類爲可變的,在多線程併發環境中會有線程安全問題。

(1)能夠使用鎖來處理併發問題。html

(2)使用JDK8  Instant 或 LocalDateTime替代。

安全

2.Calendar的子類爲可變的,在多線程併發環境中會有線程安全問題。

(1)能夠使用鎖來處理併發問題。多線程

(2)使用JDK8  LocalDateTime 替代。併發

3.DateFormat和SimpleDateFormat不是線程安全的緣由

(1)DateFormat中calendar是共享變量,其子類SimpleDateFormat中也是共享變量。app

DateFormat源碼:ide

public abstract class DateFormat extends Format {this

/**
* 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.
*
* <p>Subclasses should initialize this field to a {@link Calendar}
* appropriate for the {@link Locale} associated with this
* <code>DateFormat</code>.
* @serial
*/
protected Calendar calendar;spa

(2)SimpleDateFormat format方法源碼:線程

    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 方法,可能一個線程剛設置好 time 值另外的一個線程立刻把設置的 time 值給修改了致使返回的格式化時間多是錯誤的。code

4.SimpleDateFormat線程安全使用。

(1)使用ThreadLocal處理static方法

    public static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };
System.out.println(df.get().format(new Date()));
2019-12-14

(2)使用JDK8  DateTimeFormatter 替代。

 

參考:https://www.cnblogs.com/wupeixuan/p/11511915.html?utm_source=gold_browser_extension

  《阿里巴巴Java開發手冊》

相關文章
相關標籤/搜索