Fork me on GitHub

SimpleDateFormat简介及替代方案

简介

SimpleDateFormat是一个时间格式化工具,可以将字符串格式化时间Date类型,也可以将Date类型格式化为字符串String类型,但其线程不安全。

常用方法

public final String format(Date date):将时间格式化为我们想要的字符串。
public Date parse(String source):将字符串格式化为Date类型。

代码

  • format方法
static SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    static ArrayList<Date>  list=new ArrayList<>();
    static {
        // 每个线程对应处理的Date对象
        // 我将会开启10个线程
        Date date1 = new Date(2011-1900, Calendar.JANUARY,1);
        Date date2 = new Date(2012-1900, Calendar.JANUARY,1);
        Date date3 = new Date(2013-1900, Calendar.JANUARY,1);
        Date date4 = new Date(2014-1900, Calendar.JANUARY,1);
        Date date5 = new Date(2015-1900, Calendar.JANUARY,1);
        Date date6 = new Date(2016-1900, Calendar.JANUARY,1);
        Date date7 = new Date(2017-1900, Calendar.JANUARY,1);
        Date date8 = new Date(2018-1900, Calendar.JANUARY,1);
        Date date9 = new Date(2019-1900, Calendar.JANUARY,1);
        Date date10 = new Date(2020-1900, Calendar.JANUARY,1);
        list.add(date1);
        list.add(date2);
        list.add(date3);
        list.add(date4);
        list.add(date5);
        list.add(date6);
        list.add(date7);
        list.add(date8);
        list.add(date9);
        list.add(date10);

    }
    /**
     *  线程不安全
     *  线程执行前和执行后,数据不一致
     *
     *
     **/
    public void formatdemo(){
        ExecutorService service= Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int t = i;
            service.execute(()->{
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Date date = list.get(t);
                String format = SimpleDateFormatDemo.format.format(date);
                System.out.println("线程"+Thread.currentThread().getName()+" 执行前: "+date);
                System.out.println("线程"+Thread.currentThread().getName()+" 执行结果后:"+format);
            });
        }
    }
  • 执行结果
    image

线程3执行前 和 执行后结果不一致,说明线程不安全

  • parse方法
public void parsedemo(){
        ExecutorService service= Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int t = i;
            service.execute(()->{
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    System.out.println("线程"+Thread.currentThread().getName()+" 执行结果后:"+format.parse("2021-12-12 12:23:23"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            });
        }
    }
  • 执行结果
    出现异常: Exception in thread "pool-1-thread-1" java.lang.NumberFormatException: multiple points

线程不安全

解决办法

使用ThreadLocal进行替代

代码

public static  final ThreadLocal<DateFormat> df=new ThreadLocal<DateFormat>(){
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };

    static ArrayList<Date> list=new ArrayList<>();
    static {
        // 每个线程对应处理的Date对象
        // 我将会开启10个线程
        Date date1 = new Date(2011-1900, Calendar.JANUARY,1);
        Date date2 = new Date(2012-1900, Calendar.JANUARY,1);
        Date date3 = new Date(2013-1900, Calendar.JANUARY,1);
        Date date4 = new Date(2014-1900, Calendar.JANUARY,1);
        Date date5 = new Date(2015-1900, Calendar.JANUARY,1);
        Date date6 = new Date(2016-1900, Calendar.JANUARY,1);
        Date date7 = new Date(2017-1900, Calendar.JANUARY,1);
        Date date8 = new Date(2018-1900, Calendar.JANUARY,1);
        Date date9 = new Date(2019-1900, Calendar.JANUARY,1);
        Date date10 = new Date(2020-1900, Calendar.JANUARY,1);
        list.add(date1);
        list.add(date2);
        list.add(date3);
        list.add(date4);
        list.add(date5);
        list.add(date6);
        list.add(date7);
        list.add(date8);
        list.add(date9);
        list.add(date10);

    }
    /**
     *  线程不安全
     *  线程执行前和执行后,数据不一致
     *
     *
     **/
    public void formatdemo(){
        ExecutorService service= Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int t = i;
            service.execute(()->{
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Date date = list.get(t);
                System.out.println("线程"+Thread.currentThread().getName()+" 执行前: "+date);
                System.out.println("线程"+Thread.currentThread().getName()+" 执行结果后:"+ df.get().format(date));
            });
        }
    }

    /**
     *  Exception in thread "pool-1-thread-1" java.lang.NumberFormatException: multiple points
     *  线程不安全
     **/
    public void parsedemo(){
        ExecutorService service= Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int t = i;
            service.execute(()->{
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    System.out.println("线程"+Thread.currentThread().getName()+" 执行结果后:"+df.get().parse("2021-12-12 12:23:23"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            });
        }
    }

Gitee地址

https://gitee.com/zhuayng/foundation-study/tree/develop/JavaBasis/Tools/src/main/java/com/yxkj/javabasistools/tools/date

posted @ 2020-04-27 14:29  晨度  阅读(496)  评论(0编辑  收藏  举报