SimpleDateFormat非線程安全

類SimpleDateFormat主要負(fù)責(zé)日期的轉(zhuǎn)換與格式化,但在多線程的環(huán)境中,使用此類容易造成數(shù)據(jù)轉(zhuǎn)換及處理的不準(zhǔn)確,因?yàn)镾impleDateFormat類并不是線程安全的。

出現(xiàn)異常

本示例將實(shí)現(xiàn)實(shí)用類SimpleDateFormat在多線程環(huán)境下處理日期但得出的結(jié)果卻是錯(cuò)誤的情況,這也是在多線程環(huán)境開發(fā)中容易遇到的問題。

類MyThread.java代碼如下:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyThread extends Thread {

    private SimpleDateFormat sdf;
    private String dateString;

    public MyThread(SimpleDateFormat sdf, String dateString) {
        super();
        this.sdf = sdf;
        this.dateString = dateString;
    }

    @Override
    public void run() {
        try {
            Date dateRef = sdf.parse(dateString);
            String newDateString = sdf.format(dateRef).toString();
            if (!newDateString.equals(dateString)) {
                System.out.println("ThreadName=" + this.getName()
                        + "報(bào)錯(cuò)了 日期字符串:" + dateString + " 轉(zhuǎn)換成的日期為:"
                        + newDateString);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }

    }

}

運(yùn)行類Test.java代碼如下:

import java.text.SimpleDateFormat;

import extthread.MyThread;

public class Test {

    public static void main(String[] args) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        String[] dateStringArray = new String[] { "2000-01-01", "2000-01-02",
                "2000-01-03", "2000-01-04", "2000-01-05", "2000-01-06",
                "2000-01-07", "2000-01-08", "2000-01-09", "2000-01-10" };

        MyThread[] threadArray = new MyThread[10];
        for (int i = 0; i < 10; i++) {
            threadArray[i] = new MyThread(sdf, dateStringArray[i]);
        }
        for (int i = 0; i < 10; i++) {
            threadArray[i].start();
        }

    }
}

程序運(yùn)行后的結(jié)果如下:

ThreadName=Thread-4報(bào)錯(cuò)了 日期字符串:2000-01-05 轉(zhuǎn)換成的日期為:2000-02-24
ThreadName=Thread-5報(bào)錯(cuò)了 日期字符串:2000-01-06 轉(zhuǎn)換成的日期為:0005-02-24
ThreadName=Thread-8報(bào)錯(cuò)了 日期字符串:2000-01-09 轉(zhuǎn)換成的日期為:0001-01-10
ThreadName=Thread-9報(bào)錯(cuò)了 日期字符串:2000-01-10 轉(zhuǎn)換成的日期為:0001-01-10

從控制臺(tái)中打印的結(jié)果來看,使用單例的SimpleDateFormat類在多線程的環(huán)境中處理日期,極易出現(xiàn)日期轉(zhuǎn)換錯(cuò)誤的情況。

解決異常方法1

類MyThread.java代碼如下:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import tools.DateTools;

public class MyThread extends Thread {

    private SimpleDateFormat sdf;
    private String dateString;

    public MyThread(SimpleDateFormat sdf, String dateString) {
        super();
        this.sdf = sdf;
        this.dateString = dateString;
    }

    @Override
    public void run() {
        try {
            Date dateRef = DateTools.parse("yyyy-MM-dd", dateString);
            String newDateString = DateTools.format("yyyy-MM-dd", dateRef)
                    .toString();
            if (!newDateString.equals(dateString)) {
                System.out.println("ThreadName=" + this.getName()
                        + "報(bào)錯(cuò)了 日期字符串:" + dateString + " 轉(zhuǎn)換成的日期為:"
                        + newDateString);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }

    }

}

類DateTools.java代碼如下:

public class DateTools {

    public static Date parse(String formatPattern, String dateString)
            throws ParseException {
        return new SimpleDateFormat(formatPattern).parse(dateString);
    }

    public static String format(String formatPattern, Date date) {
        return new SimpleDateFormat(formatPattern).format(date).toString();
    }

}

運(yùn)行類Test.java代碼與前面一節(jié)是一樣的。
控制臺(tái)中沒有輸入任何異常。解決處理錯(cuò)誤的原理其實(shí)就是創(chuàng)建了多個(gè)SimpleDateFormat類的實(shí)例。

解決異常方法2

ThreadLocal類能使線程綁定到指定的對(duì)象。使用該類也可以解決多線程環(huán)境下SimpleDateFormat類處理錯(cuò)誤的情況。

類MyThread.java代碼如下:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import tools.DateTools;

public class MyThread extends Thread {

    private SimpleDateFormat sdf;
    private String dateString;

    public MyThread(SimpleDateFormat sdf, String dateString) {
        super();
        this.sdf = sdf;
        this.dateString = dateString;
    }

    @Override
    public void run() {
        try {
            Date dateRef = DateTools.getSimpleDateFormat("yyyy-MM-dd").parse(dateString);
            String newDateString = DateTools.getSimpleDateFormat("yyyy-MM-dd")
                    .format(dateRef).toString();
            if (!newDateString.equals(dateString)) {
                System.out.println("ThreadName=" + this.getName()
                        + "報(bào)錯(cuò)了 日期字符串:" + dateString + " 轉(zhuǎn)換成的日期為:"
                        + newDateString);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }

    }

}

類DateTools.java代碼如下:

import java.text.SimpleDateFormat;

public class DateTools {

    private static ThreadLocal<SimpleDateFormat> tl = new ThreadLocal<SimpleDateFormat>();

    public static SimpleDateFormat getSimpleDateFormat(String datePattern) {
        SimpleDateFormat sdf = null;
        sdf = tl.get();
        if (sdf == null) {
            sdf = new SimpleDateFormat(datePattern);
            tl.set(sdf);
        }
        return sdf;
    }

}

運(yùn)行類Test.java代碼與前面小節(jié)是一樣的。
控制臺(tái)沒有信息被輸出,看來運(yùn)行結(jié)果是正確的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,545評(píng)論 19 139
  • Cartographer安裝流程 安裝與編譯 0. 安裝所有依賴項(xiàng) $ sudo apt-get insta...
    bizarrez閱讀 308評(píng)論 0 0
  • 知道夏目友人帳更新第五季的消息,已經(jīng)是三天之后了。 第一次接觸這部動(dòng)畫片還是在上大學(xué)的時(shí)候,感覺日子多的簡(jiǎn)直過不完...
    陰冷未遂閱讀 462評(píng)論 5 4
  • 新人余生報(bào)到。 窮困潦倒的目前吶,我又提起了筆,哈哈,自知文筆不好,所以正在學(xué)習(xí)之中。玩這個(gè)呢是希望這個(gè)AP...
    蠢貨_cf26閱讀 147評(píng)論 0 0
  • 從林梢間溜過夏之風(fēng), 親和,柔軟, 如伊的手緊握。 我記不起伊的模樣, 只記得伊笑的時(shí)候, 眉目彎彎。 從林梢間溜...
    肖小小的小閱讀 227評(píng)論 3 3

友情鏈接更多精彩內(nèi)容