还在用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" ...
随机推荐
- ScheduleMaster新特性之延时任务初体验
ScheduleMaster在上个月底更新到了2.0版本,在功能和代码以及文档上都往前跨了很大一步,详细信息可以参考这篇文章:https://www.cnblogs.com/hohoa/p/12772 ...
- noi7219 复杂的整数划分问题
noi7219 复杂的整数划分问题 #include <bits/stdc++.h> using namespace std; ; int dp1[maxn][maxn], dp2[max ...
- javaWeb普通类获取ApplicationContext
网上看了很多关于获取ApplicationContext的方法,五大方法,但是我用web服务使用成功的就这一个,自己记忆下. import javax.servlet.ServletContextEv ...
- Spring 自动装配 byType
自动装配 byType,这种模式由属性类型指定自动装配. Spring 容器看作 beans,在 XML 配置文件中 beans 的 autowire 属性设置为 byType.然后,如果它的 typ ...
- 浅析String、StringBuilder、StringBuffer
谈谈我对 String.StringBuilder.StringBuffer 的理解 StringBuilder.StringBuffer 和 String 一样,都是用于存储字符串的. 1.那既然有 ...
- sklearn学习:为什么roc_auc_score()和auc()有不同的结果?
为什么roc_auc_score()和auc()有不同的结果? auc():计算ROC曲线下的面积.即图中的area roc_auc_score():计算AUC的值,即输出的AUC 最佳答案 AUC并 ...
- python_Excel_xlwt
xlwt 创建excel,向excel写入数据,并保存数据 安装 推荐方法: 通过pip 安装,方便简洁,如下图所示: 导入 import xlrd 创建workbook(即excel) book = ...
- npm执行清理缓存失败npm cache clean
C:\Users\you name>npm cache cleannpm ERR! As of npm@5, the npm cache self-heals from corruption i ...
- [不得不知道系列]Java线程面试你不得不知道的基础知识一
Java内存管理面试指南一 Java基础面试指南一 Java基础面试指南二 Java基础面试指南三 Java基础面试指南四 Java线程面试指南一 Java线程面试指南二 Redis面试指南一 Kaf ...
- 【GAN】GAN设计与训练集锦
以下内容纯属经验之谈,无公式推断!部分内容源自其他博客或课程,并已标注来源. 问题篇[1] 1.模式崩溃 在某个模式(mode)下出现大量重复样本,如左图中,生成的样本分布靠得很近,较聚集,可视化如右 ...