求求你别用SimpleDateFormat了!
前言
啊哈哈,标题写的比较随意了,其实呢最近在各种面试以及博客中,SimpleDateFormat出镜率确实是比较高了,为什么?其实聪明的你们肯定知道,那必须是有坑呗,是的,那我们就以案例来分析一下到底会有那些坑,或者还有没有其他更优的替代方案呢?
正文
首先我们来看一下可能会出现在DateUtils中的写法:
private static final SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static Date formatDate(String date) throws ParseException {
return dayFormat.parse(date);
}
当我们在单线程的程序中调用 formatDate(date) ,此时并不会出现任何问题(如果这也出问题那还玩什么...) ,然而当我们的程序在多线程并发执行调用这个方法的时候。
ExecuterService es = ExecuterService.newFixedThreadPool(50);
for( ... ){
es.execute( () -> {
System.out.println(parse("2018-11-11 10:35:20"));
})
}
此时你会发现打印出来的时间有些是错误,程序甚至会抛出异常NumberFormatException??为什么会出现这种情况呢?我们可以直接查看SimpleDateFormat.parse() 方法的源码一探究竟。
private StringBuffer format(Date date, StringBuffer toAppendTo,
FieldDelegate delegate) {
// Convert input date to time field list calendar.setTime(date); boolean useDateFormatSymbols = useDateFormatSymbols(); for (int i = 0; i < compiledPattern.length; ) { int tag = compiledPattern\[i\] >>> 8; int count = compiledPattern\[i++\] & 0xff; if (count == 255) { count = compiledPattern\[i++\] << 16; count |= compiledPattern\[i++\]; }
从源码可以看到,在多线程的环境中,执行到第五行 calendar进行操作的时候,后面的线程有可能会覆盖上一个线程设置好的值,此时就导致前面线程执行的结果被覆盖而返回了一个错误的值。
那我们该如何避免这个坑呢?
1、使用ThreadLocal,每个线程中返回各自的实例,避免了多线程环境中共用同一个实例而导致的问题。
private static ThreadLocal<SimpleDateFormat> simpleDateFormatThreadLocal = new ThreadLocal<>();
public static Date formatDate(String date) throws ParseException {
SimpleDateFormat dayFormat = getSimpleDateFormat();
return dayFormat.parse(date);
}
private static SimpleDateFormat getSimpleDateFormat() {
SimpleDateFormat simpleDateFormat = simpleDateFormatThreadLocal.get();
if (simpleDateFormat == null){
simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
simpleDateFormatThreadLocal.set(simpleDateFormat);
}
return simpleDateFormat;
}
需要注意一点的是,ThreadLocal的使用过程中也是有小坑需要注意的,大家可以参考一下其他的资料,以后可以抽空聊聊这个话题。
2、推荐升级到JDK8+,使用LocalDateTime,LocalDate,LocalTime来代替,具体的用法请自行参考API,当然JDK8所带来的Lambda,Stream等特性也是值得一试的。
3、使用三方包,推荐Joda-Time,对于日期的增减操作也是相当便捷。
github:https://github.com/JodaOrg/joda-time
求求你别用SimpleDateFormat了!的更多相关文章
- SimpleDateFormat使用详解——日期、字符串应用
public class SimpleDateFormat extends DateFormat SimpleDateFormat 是一个以国别敏感的方式格式化和分析数据的具体类. 它允许格式化 (d ...
- SimpleDateFormat转换时间格式
SimpleDateFormat有两个常用的方法parse和format 其中SimpleDateFormat在创建时有一下集中格式可以选择 SimpleDateFormat sdf = new Si ...
- DateUtil(SimpleDateFormat)
import java.util.Calendar; import java.util.Date; import java.text.SimpleDateFormat; public class Da ...
- SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
java日期格式大全 format SimpleDateFormat(转) SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH ...
- java 中的SimpleDateFormat、Date函数以及字符串和Date类型互转
SimpleDateFormat是一个以与语言环境有关的方式来格式化和解析日期的具体类.它允许进行格式化(日期 -> 文本).解析(文本 -> 日期)和规范化. SimpleDateFor ...
- java日期处理SimpleDateFormat等
1.mysql数据库中有这样一个表: mysql> select * from test_table;+----------+---------------------+| username | ...
- SimpleDateFormat的应用
import java.text.SimpleDateFormat;import java.util.Date;public class Main { public static void ma ...
- 使用 Date 和 SimpleDateFormat 类表示时间、Calendar类和Math类
一. Date 和 SimpleDateFormat类表示时间 在程序开发中,经常需要处理日期和时间的相关数据,此时我们可以使用 java.util 包中的 Date 类.这个类最主要的作用就是获取当 ...
- Java SimpleDateFormat使用
SimpleDateFormat 是一个格式化日期的具体类. 它允许格式化 (date -> text) 和标准化. SimpleDateFormat 允许以为日期-时间格式化选择任何用户指定的 ...
随机推荐
- C++中的内联函数和C中的宏定义的区别
在C++中内联函数: 内联函数即是在函数的声明和和定义前面加上“inline”关键字,内联函数和常规函数一样,都是按照值来传递参数的,如果参数为表达式,如4.5+7.5,则函数将传递表达式的值(这里为 ...
- BZOJ_1691_[Usaco2007 Dec]挑剔的美食家_贪心
BZOJ_1691_[Usaco2007 Dec]挑剔的美食家_贪心 题意: 与很多奶牛一样,Farmer John那群养尊处优的奶牛们对食物越来越挑剔,随便拿堆草就能打发她们午饭的日子自然是一去不返 ...
- 权限系统与RBAC模型概述[绝对经典]
0. 前言 一年前,我负责的一个项目中需要权限管理.当时凭着自己的逻辑设计出了一套权限管理模型,基本原理与RBAC非常相似,只是过于简陋.当时google了一些权限管理的资料,从中了解到早就有了RBA ...
- go语言调度器源代码情景分析之一:开篇语
专题简介 本专题以精心设计的情景为线索,结合go语言最新1.12版源代码深入细致的分析了goroutine调度器实现原理. 适宜读者 go语言开发人员 对线程调度器工作原理感兴趣的工程师 对计算机底层 ...
- Fiddler 接口测试(Composer)的使用方法及并发测试
下载地址:https://www.telerik.com/download/fiddler 一.Composer简介 右侧Composer区域,是测试接口的界面: 相关说明: 1.请求方式:点开可以勾 ...
- WPF TextBox 正则验证 大于等于0 小于等于1 的两位小数
正则:^(0\.\d+|[1-9][0-9]|1)$ TextBox绑定正则验证 <TextBox x:Name="txb" MaxLength="6" ...
- 系统的讲解 - PHP 缓存技术
目录 概述 浏览器缓存 文件缓存 NoSQL缓存 WEB服务器缓存 Opcode缓存 小结 关于缓存的常见问题 概述 缓存已经成了项目中是必不可少的一部分,它是提高性能最好的方式,例如减少网络I/O. ...
- Hystrix源码解析
1. Hystrix源码解析 1.1. @HystrixCommand原理 直接通过Aspect切面来做的 1.2. feign hystrix原理 它的本质原理就是对HystrixCommand的动 ...
- JQuery --- 第一期 (初识jQuery, JQuery核心函数和工具方法)
个人学习笔记 初识jQuery 1.我的第一个JQuery <!DOCTYPE html> <html lang="en"> <head> & ...
- Web地图导图总结
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1. 背景 地图端展示了各类制图效果,用户希望可以一键生成报表,其中核心 ...