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


}

猜你喜欢

转载自blog.csdn.net/liyingying111111/article/details/83088944
今日推荐