解決SimpleDateFormat線程安全問題 NumberFormatException: multiple points

SimpleDateFormat是線程不安全的類,一般不要定義為static變量,如果定義為static,必須通過加鎖等方式保證線程安全。

例如下面一段代碼,啟動10個線程,同時使用一個SimpleDateFormat實例去格式化Date

import java.text.ParseException;
import java.text.SimpleDateFormat;
public class SimpleDateFormatDemo {

    // (1)創(chuàng)建單例實例
    static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public static void test1() {
        // (2)創(chuàng)建多個線程,并啟動
        for (int i = 0; i < 10; ++i) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {// (3)使用單例日期實例解析文本
                        System.out.println(sdf.parse("2019-03-07 15:17:27"));
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
            });
            thread.start();// (4)啟動線程
        }

    }

    public static void main(String[] args) {

        test1();

    }

}

啟動以后拋出如下異常:

Exception in thread "Thread-5" Exception in thread "Thread-4" Exception in thread "Thread-0" java.lang.NumberFormatException: multiple points
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1890)
    at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
    at java.lang.Double.parseDouble(Double.java:538)
    at java.text.DigitList.getDouble(DigitList.java:169)
    at java.text.DecimalFormat.parse(DecimalFormat.java:2089)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
    at java.text.DateFormat.parse(DateFormat.java:364)
    at net.ijiangtao.tech.framework.spring.ispringboot.demo.demostart.thread.demo.SimpleDateFormatDemo$1.run(SimpleDateFormatDemo.java:18)

怎么解決這個問題呢?下面推薦一種解決方案:

      // (1)創(chuàng)建localDateFormat實例
    static ThreadLocal<DateFormat> localDateFormat = new ThreadLocal<DateFormat>() {
        @Override
        public SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };

    public static void test() {
        // (2)創(chuàng)建多個線程,并啟動
        for (int i = 0; i < 10; ++i) {
            Thread thread = new Thread(new Runnable() {
                public void run() {
                    try {// (3)解析文本
                        // System.out.println(sdf.parse("2019-03-07 15:17:27"));
                        System.out.println(localDateFormat.get().parse("2019-03-07 15:17:27"));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            thread.start();// (4)啟動線程
        }
    }

    public static void main(String[] args) {
        test();
    }

ThreadLocal,也叫做線程本地變量或者線程本地存儲,ThreadLocal為變量在每個線程中都創(chuàng)建了一個副本,那么每個線程可以訪問自己內(nèi)部的副本變量,這樣就避免了SimpleDateFormat線程不安全的問題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 進程和線程 進程 所有運行中的任務(wù)通常對應(yīng)一個進程,當(dāng)一個程序進入內(nèi)存運行時,即變成一個進程.進程是處于運行過程中...
    勝浩_ae28閱讀 5,142評論 0 23
  • JAVA并發(fā)編程與高并發(fā)解決方案 - 并發(fā)編程 三 相關(guān)文章 JAVA并發(fā)編程與高并發(fā)解決方案 - 并發(fā)編程 一 ...
    chuIllusions丶閱讀 2,784評論 1 7
  • 進程和線程 進程 所有運行中的任務(wù)通常對應(yīng)一個進程,當(dāng)一個程序進入內(nèi)存運行時,即變成一個進程.進程是處于運行過程中...
    小徐andorid閱讀 2,850評論 3 53
  • ??一個任務(wù)通常就是一個程序,每個運行中的程序就是一個進程。當(dāng)一個程序運行時,內(nèi)部可能包含了多個順序執(zhí)行流,每個順...
    OmaiMoon閱讀 1,707評論 0 12
  • 一個朋友失魂落魄地來找我。她嚎啕大哭:“談了半年戀愛的那個她愛得很深的男人居然早就已經(jīng)有女朋友了,他欺騙了她?!蔽?..
    張曉棲閱讀 547評論 0 0