还在用SimpleDateFormat格式化时间?小心经理锤你
还在用SimpleDateFormat格式化时间?小心经理锤你

场景
本来开开心心的周末时光,线上突然就疯狂报错,以为程序炸了,截停日志,发现是就是类似下述一段错误
java.lang.NumberFormatException: For input string: ".202006E.202006E44"
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:1869)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
at java.text.DateFormat.parse(DateFormat.java:364)
at com.github.springtools.SimpleDateFormatTest.lambda$null$0(Xxxxxxx.java:2020)
at java.lang.Thread.run(Thread.java:748)
定位到错误处,发现是一个时间格式化(SimpleDateFormat)的异常,一个时间格式化怎么会导致这种错误,还使得接口不能正常调用
测试
拉出来,使用模拟接口多线程的环境,单独进行测试.....
package com.github.springtools;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.stream.IntStream;
public class SimpleDateFormatTest {
public static final SimpleDateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd");
public static void main(String[] args) throws ParseException {
System.out.println(FORMAT.parse("2020-06-06"));
System.out.println("--------单个调用结束--------");
System.out.println("--------多线程调用开始--------");
IntStream.rangeClosed(0, 10)
.forEach(i -> new Thread(() -> {
try {
System.out.println(FORMAT.parse("2020-06-06"));
} catch (ParseException e) {
e.printStackTrace();
}
}).start());
}
}
输出
Sat Jun 06 00:00:00 CST 2020
--------单个调用结束--------
--------多线程调用开始--------
Sat Jun 06 00:00:00 CST 2020
Sat Jun 06 00:00:00 CST 2020
Exception in thread "Thread-7" Exception in thread "Thread-8" java.lang.NumberFormatException: For input string: ".202006E.202006E44"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.lang.Double.parseDouble(Double.java:538)
罪魁祸手浮出水面,就是SimpleDateFormat的锅

线程不安全,去找Java文档里的SimpleDateFormat: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.日期格式不同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问一种格式,则必须在外部进行同步。
解决方法
使用ThreadLocal
// ThreadLocal
public static final ThreadLocal<SimpleDateFormat> THREADLOCAL_FORMAT = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
IntStream.rangeClosed(0, 5)
.forEach(i -> new Thread(() -> {
try {
System.out.println("ThreadLocal:" + THREADLOCAL_FORMAT.get().parse("2020-06-06"));
} catch (ParseException e) {
e.printStackTrace();
}
}).start());
使用Java 8中的时间处理
public static final DateTimeFormatter JAVA8_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
IntStream.rangeClosed(0, 5)
.forEach(i -> new Thread(() -> {
try {
System.out.println("JAVA8_FORMATTER:" + JAVA8_FORMATTER.parse("2020-06-06"));
} catch (ParseException e) {
e.printStackTrace();
}
}).start());
总结
使用多线程的时候,一定要考虑到其调用到的实例变量,Java8中时间格式化DateTimeFormatter是用final修饰的,不可变类,所以是线程安全的,或者在线程中调用ThreadLocal也是可以的
还在用SimpleDateFormat格式化时间?小心经理锤你的更多相关文章
- SimpleDateFormat 格式化时间少了12个小时
SimpleDateFormat 格式化时间少了12个小时 标签(空格分隔): java SimpleDateFormat H:一天中的小时数:0-23 h: am/pm 小时数: 1-12 publ ...
- java-使用SImpleDateFormat格式化时间输出
之前有篇博客是使用NSDateFormatter来对时间进行格式化输出,但使用起来有点繁琐,今天介绍下最近刚刚使用的SimpleDateFormat. public class SimpleDateF ...
- 记一次使用SimpleDateFormat 格式化时间时遇到的问题
网上的使用方法一大堆,我就不再介绍了,就写一下自己遇到的问题. 先来实现一下获取当前时间: SimpleDateFormat simpleDateFormat =new SimpleDateForma ...
- Java-Runoob-高级教程-实例-时间处理:01. Java 实例 - 格式化时间(SimpleDateFormat)
ylbtech-Java-Runoob-高级教程-实例-时间处理:01. Java 实例 - 格式化时间(SimpleDateFormat) 1.返回顶部 1. Java 实例 - 格式化时间(Sim ...
- 【 格式化时间(SimpleDateFormat)用法】
将特定字符串转换成Date格式 可以通过 new 一个 SimpleDateFormat 对象,通过对象调用parse方法实现 示例代码: String time = "2019-11-09 ...
- java 格式化时间
java.text.DateFormat format1 = new java.text.SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); form ...
- SimpleDateFormat格式化日期
SimpleDateFormat格式化日期 import java.text.SimpleDateFormat;import java.util.Date;public class test { pu ...
- JAVA格式化时间日期
JAVA格式化时间日期 import java.util.Date; import java.text.DateFormat; /** * 格式化时间类 * DateFormat.FULL = 0 * ...
- Java格式化时间
Java格式化时间 将秒或者毫秒值格式化成指定格式的时间 效果图 工具类 工具类里我只列出了一种格式的格式化方式,可以根据自己的需求,修改"yyyy-MM-dd hh:mm:ss" ...
随机推荐
- java ->大的数据运算(BigInteger)
大数据运算 BigInteger java中long型为最大整数类型,对于超过long型的数据如何去表示呢.在Java的世界中,超过long型的整数已经不能被称为整数了,它们被封装成BigIntege ...
- 使用windows(win7和win10),最好用chocolatey
Win10平台使用PowerShell命令行choco来安装所需开源软件. 步骤如下: 打开Chocolatey 官方网站,The package manager for windows,这很巨硬. ...
- orcle增删改操作及alter修改表字段操作
orcle增删改操作:操作前确保当前用户有增删改的权限. --创建表 create table itcast( pid ), pname ) ); drop table itcast; --复制表 c ...
- SpringMvc上传图片及表单提交(单文件+实体类参数提交)
前两天做项目用到了Springmvc的文件上传来上传图片,由于和这个普通的Java文件上传处理流程不太一样,所以做的时候碰了壁,一顿百度,博客,要不就是一部分代码,要不就是看不懂,用不会的代码,下面来 ...
- Redux:中间件
redux中间件概念 比较容易理解. 在使用redux时,改变store state的一个固定套路是调用store.dispatch(action)方法,将action送到reducer中. 所谓中间 ...
- mysql小白系列_11 MHA补充
1.ssh_user 使用VIP方式需要在新的master主机上对网卡启alias并设置IP,普通用户没权限 2.VIP问题 配置以后主从后,在MHA管理节点启动masterha_manager,VI ...
- 26-13 order by排序
表中数据是集合,集合是没有顺序的.order by返回的数据是有顺序的,故此我们把order by以后返回的数据集合叫“游标”. --------------------------通过order b ...
- python 计算异或
'''******************************************************** Func Name: addZero Para: x : 字符串 y : 长度 ...
- Java——日期获取和日期格式化
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; impor ...
- 快速上手Alibaba Arthas
点击返回上层目录 原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94 Arthas 本文主要聚焦于快速上手并使用Arthas,所以对于基本的概 ...