java8的新特性之-----日期格式化的執行緒安全問題
阿新 • • 發佈:2018-12-06
SimpleDateFormat是執行緒非安全的。那麼在多執行緒中,就會出現錯誤的結果如下程式碼:
public static void main(String[] args){ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); Callable<Date> callable = new Callable<Date>() { @Override public Date call() throws Exception { //由於執行緒非安全,所以往pool中同時放入100個任務並開啟10000個執行緒去執行如下 的程式碼就會報錯。100不報錯,就改成1000,1000不報錯就改成10000.你的機子 越牛逼。這個數字就越大。但是肯定會報錯 return sdf.parse("20181012"); }; }; List<Future<Date>> dates = new ArrayList(); ExecutorService pool = Executors.newFixedThreadPool(10); for(int i=0;i<10000;i++){ LocalDates.add(pool.submit(callable)); } dates.forEach((Future<Date> dateFuture) -> { try { System.out.println(dateFuture.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }); pool.shutdown(); }
這個時候我們會想到一個類。可以實現SimpleDateFormat的執行緒安全。那就是ThreadLocal。怎麼做呢?如下:
把DateFormat物件初始化後放入到ThreadLocal中加鎖。
1:建立DateFormatThreadLocal類 public class DateFormatThreadLocal { private static final ThreadLocal<DateFormat> threadLocalDate = new ThreadLocal<DateFormat>(){ protected Date initialValue() { return new SimpleDateFormat("yyyyMMdd"); } } public static Date convert(String source){ return threadLocalDate.get().parse(source); } }
再執行上述程式碼就ok了。
java1.8就不用這麼麻煩了。它提供了LocalDate類 和 DateTimeFormat類。具體程式碼如下這兩個類似執行緒安全的
import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; /** * : 描述資訊 * * @author liyy * @LocalDate 2018-10-16 10:20 */ public class TestJava8 { public static void main(String[] args){ // SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); //定義格式化的物件 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd"); Callable<LocalDate> callable = new Callable<LocalDate>() { @Override public LocalDate call() throws Exception { //呼叫LocalDate.parse方法並傳入格式化物件即可 return LocalDate.parse("20181012",dtf); }; }; ExecutorService pool = Executors.newFixedThreadPool(10); List<Future<LocalDate>> LocalDates = new ArrayList(); for(int i=0;i<10000;i++){ LocalDates.add(pool.submit(callable)); } LocalDates.forEach((Future<LocalDate> LocalDateFuture) -> { try { System.out.println(LocalDateFuture.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }); pool.shutdown(); } }