专栏首页JVMGCJAVA日期安全格式化之SimpleDateFormat和jodaTime,DateTimeFormatter
原创

JAVA日期安全格式化之SimpleDateFormat和jodaTime,DateTimeFormatter

SimpleDateFormat线程不安全的日期格式化库

SimpleDateFormatJAVA提供的一个日期转换类。

package com.rumenz.task;

import java.text.SimpleDateFormat;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

//线程不安全
public class DataFormat {

    private static SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyyMMdd");
    private static Integer clientTotal=5000;
    private static Integer threadTotal=200;

    public static void main(String[] args) throws Exception{
        ExecutorService executorService = Executors.newCachedThreadPool();
        final Semaphore semaphore=new Semaphore(threadTotal);
        final CountDownLatch countDownLatch=new CountDownLatch(clientTotal);
        for (int i = 0; i <clientTotal ; i++) {
            executorService.execute(()->{
                try{
                    semaphore.acquire();
                    update();
                    semaphore.release();
                }catch (Exception e){
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            });

        }
        countDownLatch.await();
        executorService.shutdown();


    }

    private static void update() {
        try{
            simpleDateFormat.parse("20200115");
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}

运行的时候会报错,线程不安全

java.lang.NumberFormatException: For input string: "E152"
	at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
	at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
	at java.lang.Double.parseDouble(Double.java:538)
	at java.text.DigitList.getDouble(DigitList.java:169)
	at java.text.DecimalFormat.parse(DecimalFormat.java:2089)
	at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1867)
	at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
	at java.text.DateFormat.parse(DateFormat.java:364)
	at com.rumenz.task.DataFormat.update(DataFormat.java:47)
	at com.rumenz.task.DataFormat.lambda$main$0(DataFormat.java:30)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

如果要使用SimpleDateFormat可以将其做成局部变量,这样在多线程环境下就不会出现线程安全问题。或者使用synchronized给方法加锁。

jodaTime 线程安全的格式化库

引入依赖

<dependency>
  <groupId>joda-time</groupId>
  <artifactId>joda-time</artifactId>
  <version>2.9.9</version>
</dependency>
package com.keytech.task;

import org.joda.time.DateTime;

import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

//线程安全
public class DataFormat1 {

    public static Integer clientTotal=5000;
    public static Integer threadTotal=200;
    private static DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("yyyyMMdd");

    public static void main(String[] args)  throws Exception{
        ExecutorService executorService = Executors.newCachedThreadPool();
        final Semaphore semaphore=new Semaphore(threadTotal);
        final CountDownLatch countDownLatch=new CountDownLatch(clientTotal);
        for (int i = 0; i < clientTotal; i++) {
            executorService.execute(()->{
                try{
                    semaphore.acquire();
                    update();
                    semaphore.release();

                }catch (Exception e){
                    e.printStackTrace();
                }
                countDownLatch.countDown();
            });

        }
        countDownLatch.await();
        executorService.shutdown();
    }

    private static void update() {
        DateTime dateTime = DateTime.parse("20200115").toDateTime();
        System.out.println(dateTime);
    }
}

DateTimeFormatter JAVA8中线程安全的日期转换类

package com.keytech.task;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

//线程安全
public class DateFormat2 {

    public static Integer clientTotal=5000;
    public static Integer threadTotal=200;
    private  static final  DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");

    public static void main(String[] args) throws Exception{
        ExecutorService executorService = Executors.newCachedThreadPool();
        final Semaphore semaphore=new Semaphore(threadTotal);
        final CountDownLatch countDownLatch=new CountDownLatch(clientTotal);

        for (int i = 0; i < clientTotal; i++) {
            try{
                semaphore.acquire();
                update();
                semaphore.release();
            }catch (Exception e){
                e.printStackTrace();
            }
            countDownLatch.countDown();

        }

        countDownLatch.await();
        executorService.shutdown();

    }

    private static void update() {
        LocalDate localDate = LocalDate.parse("20200115", formatter);
        System.out.println(localDate);

    }
}

JAVA8中自带,直接可以使用,不需要引入其它的库。

wx.jpg

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 高并发之——SimpleDateFormat类的线程安全问题和解决方案

    首先问大家一个问题:你使用的SimpleDateFormat类还安全吗?我们一起带着这个问题来看本文。

    冰河
  • 更正《深入理解高并发编程(第1版)》中的一处错误!

    最近,有小伙伴看了我写的《深入理解高并发编程(第1版)》或者在 冰河技术 公号看了《高并发之——SimpleDateFormat类的线程安全问题和解决方案》一文...

    冰河
  • 还在用 SimpleDateFormat, 来试试 DateTimeFormatter

    1.8 以前 Java 关于日期的类是 Date 与 Calendar, 与之对应的格式化的类是 SimpleDateFormat。 上一篇介绍了在1.8 中提...

    Dylan Liu
  • 还在用 SimpleDateFormat, 来试试 DateTimeFormatter

    1.8 以前 Java 关于日期的类是 Date 与 Calendar, 与之对应的格式化的类是 SimpleDateFormat。 上一篇介绍了在1.8 中提...

    Dylan Liu
  • jdk8获取当前时间|时间加减|java8时间格式化|时间处理工具|时间比较|线程安全的时间处理方法

    在很久之前,我总结了一些jdk7版本之前的关于时间处理的一些公共方法,日期转换成字符串、指定时间加上指定天数后的日期、获取上周周一时间 等等;具体的可以戳链接查...

    小小鱼儿小小林
  • java各个时间类总结归纳,最全一篇

    本文主要针对Date、Calendar、Instant、LocalDate、LocalTime和LocalDateTime的使用做了介绍并进行了对比,同时对si...

    公众号 IT老哥
  • 为什么不建议使用Date,而是使用Java8新的时间和日期API?

    在Java 8之前,所有关于时间和日期的API都存在各种使用方面的缺陷,因此建议使用新的时间和日期API,分别从旧的时间和日期的API的缺点以及解决方法、Jav...

    武培轩
  • JSR310新日期API(三)-日期时间格式化与解析

    前一篇文章已经比较详细地介绍了JSR-310中新增的常用的日期时间类,在实际应用中,我们也十分关注这些日期时间类的格式化操作,更加通俗来说就是字符串和日期时间类...

    Throwable
  • 什么在代码中要求我们使用LocalDateTime而不是Date?

    在项目开发过程中经常遇到时间处理,但是你真的用对了吗,理解阿里巴巴开发手册中禁用static修饰SimpleDateFormat吗?

    用户1516716
  • 你还在用SimpleDateFormat格式化时间嘛?

    当多个线程使用同一个时间处理对象进行对日期的格式化的时候,会出现java.lang.NumberFormatException: multiple points...

    石的三次方
  • 玩转 Java 时间 + 面试题

    在 JDK 8 之前,Java 语言为我们提供了两个类用于操作时间,它们分别是:java.util.Date 和 java.util.Calendar,但在 J...

    架构师修炼
  • 【优雅的避坑】不安全!别再共享SimpleDateFormat变量了-日期时间处理的正确姿势

    JDK文档中已经明确表明了「SimpleDateFormat不应该用在多线程场景」中:

    行百里er
  • 还在用SimpleDateFormat格式化时间?小心经理锤你

    本来开开心心的周末时光,线上突然就疯狂报错,以为程序炸了,截停日志,发现是就是类似下述一段错误

    拾荒者的笔记
  • 为什么建议使用你 LocalDateTime ,而不是 Date?

    来源:juejin.im/post/5d7787625188252388753eae

    JAVA葵花宝典
  • Java日期处理易踩的十个坑

      我们设置了10小时,但运行结果是22点,而不是10点。因为Calendar.HOUR默认是按12小时制处理的,需要使用Calendar.HOUR_OF_DA...

    不会飞的小鸟
  • 为什么建议使用你 LocalDateTime ,而不是 Date?

    多线程并发如何保证线程安全 - 避免线程之间共享一个SimpleDateFormat对象,每个线程使用时都创建一次SimpleDateFormat对象 => 创...

    芋道源码
  • 为什么建议使用你 LocalDateTime ,而不是 Date?

    来源:juejin.im/post/5d7787625188252388753eae

    用户1516716
  • 程序员必备:Java日期处理的十个坑

    我们设置了10小时,但运行结果是22点,而不是10点。因为Calendar.HOUR默认是按12小时制处理的,需要使用Calendar.HOUROFDAY,因为...

    捡田螺的小男孩
  • SimpleDateFormat多线程下不安全!!!解决之道

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

    码农王同学

扫码关注云+社区

领取腾讯云代金券