1. 程式人生 > >java8的新特性之-----日期格式化的執行緒安全問題

java8的新特性之-----日期格式化的執行緒安全問題

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();
    }


}