SimpleDateFormat多线程下不安全!!!解决之道

格式化时间常用的就是SimpleDateFormat这个类了,然而这样的写法在单线程程序中不会出现线程不安全的问题,但是在多线程的环境下却会出现线程不安全的问题。

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


    public static Date formatDate(String date) throws ParseException {
        return simpleDateFormat.parse(date);
    }

    在多线程下环境下使用这个方法进行时间的格式化,看下执行结果是否都一致。

//当在单线程的程序中调用formatDate(String date),此时并不会出现任何问题。然而当程序在多线程并发执行调用这个方法的时候
//就会产生线程不安全的问题
    private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
    public static void main(String[] args) {
        final int threadCount = 1000;
        for (int i = 0; i < threadCount; i++) {
            Runnable runnable = () -> {
                try {
                    System.out.println(formatDate("2020-03-30 08:08:08"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            };
            executorService.submit(runnable);
        }
        executorService.shutdown();
    }

   执行结果如下:

Mon Mar 30 08:08:08 CST 2020
Mon Mar 30 08:08:08 CST 2020
Mon Mar 30 08:08:08 CST 2020
Mon Mar 30 08:08:08 CST 2020
Sun Mar 30 08:08:08 CST 20220200
Mon Mar 30 08:08:08 CST 2020
Mon Mar 30 08:08:08 CST 2020
Mon Mar 30 08:08:08 CST 2020


我们可以看到多次执行其结果不一致,为什么会出现这种情况呢?从SimpleDateFormat.parse()源码可以看到,在多线程环境下,在calendar进行操作时,后面的线程有可能会覆盖上一个线程设置好的值,这就导致了线程不安全的问题存在。

解决之道!!!

使用ThreadLocal进行避免,这样每个线程中返回各自的实例,避免了多线程环境下共用一个实例导致线程不安全的问题。

private static SimpleDateFormat getSimpleDateFormate() {
        SimpleDateFormat simpleDateFormat = threadLocal.get();
        if (simpleDateFormat == null) {
            simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
            threadLocal.set(simpleDateFormat);
        }
        return simpleDateFormat;
    }


    public static void remove() {
        threadLocal.remove();
    }


    private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");


    private static LocalDateTime dateTimeFormatter(String date) {
        return LocalDateTime.parse(date, dateTimeFormatter);
    }


    private static final ExecutorService executorService = Executors.newFixedThreadPool(5);


    public static void main(String[] args) {
        final int threadCount = 1000;
        for (int i = 0; i < threadCount; i++) {
            Runnable runnable = () -> {
                try {
                    System.out.println(formatDateWithSecurity("2020-03-30 08:08:08"));
                    remove();
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            };
            executorService.submit(runnable);
        }
        executorService.shutdown();
    }

解决之道二!!!

使用java8提供的DateTimeFormatter进行日期的格式化。

private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");


    private static LocalDateTime dateTimeFormatter(String date) {
        return LocalDateTime.parse(date, dateTimeFormatter);
    }
private static final ExecutorService executorService = Executors.newFixedThreadPool(5);


    public static void main(String[] args) {
        final int threadCount = 1000;
        for (int i = 0; i < threadCount; i++) {
            Runnable runnable = () -> {
                System.out.println(dateTimeFormatter("2020-03-30 08:08:08"));
            };
            executorService.submit(runnable);
        }
        executorService.shutdown();
    }

以上就是关于讲述SimpleDateFormate在多线程下不安全的问题和如何解决的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值