1. 程式人生 > 程式設計 >Java SimpleDateFormat執行緒安全問題原理詳解

Java SimpleDateFormat執行緒安全問題原理詳解

今天百度一些資料偶然發現SimpleDateFormat居然不是執行緒安全的,平時使用時根本沒有考慮,萬幸今天發現了這個問題,得把寫的程式碼得翻出來整理一下了。

一般我們使用的SimpleDateFormat一般是這樣寫的:

public void method() {
  ...
  DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  Date date = dateFormat.parse("2020-05-10 19:53:00");
  ...
}

這樣寫完全沒有任何問題,但我們有時候會覺得重複建立SimpleDateFormat耗費效能,就想到把SimpleDateFormat物件做為類的靜態成員變數,那麼程式碼就是這樣了:

private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

public void method() {
  ...
  Date date = dateFormat.parse("2020-05-10 19:53:00");
  ...
}

我經常在Controller做日期轉換的時候就是這麼幹的,但這樣寫很有問題,多執行緒通知執行容易出問題,要麼轉換後的結果不對,要麼報錯,我們測試一下:

public class DateUtils {
  private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

  public static Date prase(String date) throws ParseException {
    return dateFormat.parse(date);
  }

  static class Job extends Thread {
    @Override
    public void run() {
      try {
        System.out.println(this.getName() + ":" + DateUtils.prase("2020-05-10 19:53:00"));
      } catch (ParseException e) {
      }
    }
  }

  public static void main(String[] args) {
    for (int i = 0; i < 10; i++) {
      new Job().start();
    }
  }
}

測試結果如下:

Java SimpleDateFormat執行緒安全問題原理詳解

那有沒有好的解決方案呢,既不用重複建立物件,又保證執行緒安全呢?答案是有。

方法一:使用ThreadLocal

public class MyController {
  private static ThreadLocal<DateFormat> local = new ThreadLocal<DateFormat>() {
    protected DateFormat initialValue() {
      return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    };
  };
  
  public void method() {
    ...
    Date date = local.get().parse("2020-05-10 19:53:00");
    ...
  }
}

方法二:使用第三方apache提供工具包commons-lang3

import org.apache.commons.lang3.time.FastDateFormat;
public class MyController {
  public void method() {
    ...
    Date date = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss").parse("2020-05-10 19:53:00");
    ...
  }
}

推薦使用第二種,既快有方便。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。