先来看一个多线程下使用例子,看到运行结果会出现异常:

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class SimpleDateFormateTest { public static void main(String[] args) {
final DateFormat df = new SimpleDateFormat("yyyyMMdd,HHmmss");
ExecutorService ts = Executors.newFixedThreadPool(100);
for (;;) {
ts.execute(new Runnable() {
@Override
public void run() {
try {
//生成随机数,格式化日期
String format = df.format(new Date(Math.abs(new Random().nextLong())));
System.out.println(format);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
});
}
}
}

运行结果:

在并发环境下使用SimpleDateFormat,正常的打开放式如下:

为了能够在多线程环境下使用SimpleDateFormat,有这六种方法:

方法一

在需要执行格式化的地方都新建SimpleDateFormat实例,使用局部变量来存放SimpleDateFormat实例

public static  String formatDate(Date date)throws ParseException{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
}

这种方法可能会导致短期内创建大量的SimpleDateFormat实例,如解析一个excel表格里的字符串日期。

方法二

为了避免创建大量的SimpleDateFormat实例,往往会考虑把SimpleDateFormat实例设为静态成员变量,共享SimpleDateFormat对象。这种情况下就得对SimpleDateFormat添加同步。

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

public static String formatDate(Date date)throws ParseException{
synchronized(sdf){
return sdf.format(date);
}
}

这种方法的缺点也很明显,就是在高并发的环境下会导致解析被阻塞。

方法三 

方法加同步锁synchronized,在同一时刻,只有一个线程可以执行类中的某个方法。

缺点:性能较差,每次都要等待锁释放后其他线程才能进入。

方案四 使用第三方包

这个我有尝试cn.hutool和common-lang3提供的FastDateFormat 
最后的结果其实并不满意,因为这两个包都没能帮助我检查非正常时间,比如2018-07-32这种日期也被认为是正确的时期格式了

方法五(推荐)

要在高并发环境下能有比较好的体验,可以使用ThreadLocal来限制SimpleDateFormat只能在线程内共享,这样就避免了多线程导致的线程安全问题。

 private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
}; public static String format(Date date) {
return threadLocal.get().format(date);
}

方案六 DateTimeFormatter使用

Java8提供了新的日期时间API,其中包括用于日期时间格式化的DateTimeFormatter,它与SimpleDateFormat的有什么区别呢?

问题解决

两者最大的区别是,Java8的DateTimeFormatter也是线程安全的,而SimpleDateFormat并不是线程安全。

解析日期

String dateStr= "2016年10月25日";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
LocalDate date= LocalDate.parse(dateStr, formatter);

日期转换为字符串

LocalDateTime now = LocalDateTime.now();
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy年MM月dd日 hh:mm a");
String nowStr = now .format(format);

由DateTimeFormatter的静态方法ofPattern()构建日期格式,LocalDateTime和LocalDate等一些表示日期或时间的类使用parse和format方法把日期和字符串做转换。

使用新的API,整个转换过程都不需要考虑线程安全的问题。

多线程避免使用SimpleDateFormat及替代方案的更多相关文章

  1. 【多线程补充】SimpleDateFormat非线程安全与线程中、线程组中异常的处理

    1.SimpleDateFormat非线程安全的问题 类SimpleDateFormat主要负责日期的转换与格式化,但在多线程环境中,使用此类容易造成数据转换及处理的不正确,因为SimpleDateF ...

  2. Java并发编程笔记之SimpleDateFormat源码分析

    SimpleDateFormat 是 Java 提供的一个格式化和解析日期的工具类,日常开发中应该经常会用到,但是由于它是线程不安全的,多线程公用一个 SimpleDateFormat 实例对日期进行 ...

  3. SimpleDateFormat,Calendar 线程非安全的问题

    SimpleDateFormat是Java中非常常见的一个类,用来解析和格式化日期字符串.但是SimpleDateFormat在多线程的环境并不是安全的,这个是很容易犯错的部分,接下来讲一下这个问题出 ...

  4. SimpleDateFormat是线程不安全的

    线程不安全的SimpleDateFormat SimpleDateFormat是线程不安全的 SimpleDateFormat是Java提供的一个格式化和解析日期的工具类,日常开发中应该经常会用到,但 ...

  5. Java多线程编程(七)线程状态、线程组与异常处理

    一.线程的状态 线程对象在不同的运行时期有不同的状态,状态信息就存在于State枚举类中. 调用与线程有关的方法后,会进入不同的线程状态,这些状态之间某些是可双向切换的,比如WAITING和RUNNI ...

  6. Java多线程编程核心技术-第7章-拾遗增补-读书笔记

    第 7 章 拾遗增补 本章主要内容 线程组的使用. 如何切换线程状态. SimpleDataFormat 类与多线程的解决办法. 如何处理线程的异常. 7.1 线程的状态 线程对象在不同的运行时期有不 ...

  7. Java-JUC(十四):SimpleDateFormat是线程不安全的

    SimpleDateFormat是Java提供的一个格式化和解析日期的工具类,日常开发中应该经常会用到,但是由于它是线程不安全的,多线程公用一个SimpleDateFormat实例对日期进行解析.格式 ...

  8. SimpleDateFormat线程不安全的5种解决方案!

    1.什么是线程不安全? 线程不安全也叫非线程安全,是指多线程执行中,程序的执行结果和预期的结果不符的情况就叫做线程不安全. ​ 线程不安全的代码 SimpleDateFormat 就是一个典型的线程不 ...

  9. ThreadLocal总结

    一.问题抛出 SimpleDateFormat是非线程安全的,在多线程情况下会遇见问题: public static void main(String[] args) { ExecutorServic ...

随机推荐

  1. 原创的离线版 Redis 教程,给力!

    嗯,你没看错,松哥又给大家送干货来了.这次是可以离线阅读的 PDF 版教程哦. 之前一直有小伙伴问我有没有 Redis 的电子书,老实说,有是有,但是公开给大家分享,其实有一点点风险,毕竟这都是有版权 ...

  2. dedecms5.7文章页的标签随机插入到内容中并且标签的地址为其标签关联的其他文章地址

    dedecms5.7文章页的标签随机插入到内容中并且标签的地址为其他标签关联的文章地址 1 添加2个自定义函数 在dede/include/extend.func.php底部 添加如下代码 //根据文 ...

  3. 用T4生成EF框架下的DAL、IDAL、BLL、IBLL

    (一)什么是T4模板? T4,即4个T开头的英文字母组合:Text Template Transformation Toolkit. T4文本模板,即一种自定义规则的代码生成器.根据业务模型可生成任何 ...

  4. PHP格林威治时间

    echo gmdate('D, d M Y H:i:s \G\M\T'); echo '<br>'; echo gmdate ("l, d F Y H:i:s").&q ...

  5. QString判断空 isEmpty

    isEmpty Returns true if the string has no characters; otherwise returns false. QString().isEmpty(); ...

  6. Django ajax 检测用户名是否已被注册

    添加一个 register.html 页面 <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  7. dstat 系统监控命令

    tat 命令很强大,可以实时监控CPU,磁盘,网络,IO,内存等. yum install -y dstat 例: dstat  #查看全部监控信息 dstat -c  #查看cpu 使用情况

  8. 目标检测的评价标准mAP, Precision, Recall, Accuracy

    目录 metrics 评价方法 TP , FP , TN , FN 概念 计算流程 Accuracy , Precision ,Recall Average Precision PR曲线 AP计算 A ...

  9. requests---session简介

    http协议是无状态的,也就是每个请求都是独立的.那么登录后的一系列动作,都需要用cookie来验证身份是否是登录状态,为了高效的管理会话,保持会话,于是就有了session session简介 se ...

  10. ant+jmeter+jenkins自动环境搭建

    一.安装前准备 1.JDK:jdk-8u131-windows-x64 2.jmeter工具:apache-jmeter-5.1.1 3.ANT工具:apache-ant-1.10.3 4.jenki ...