SimpleDateFormatt线程不安全及解决办法
一. 为什么SimpleDateFormat不是线程安全的?
Java源码如下:
-
-
-
-
-
-
-
public class SimpleDateFormat extends DateFormat {
-
-
public Date parse(String text, ParsePosition pos){
-
-
-
Date parsedDate = calendar.getTime();
-
-
-
-
-
abstract class DateFormat{
-
-
protected Calendar calendar;
-
public Date parse(String source) throws ParseException{
-
ParsePosition pos = new ParsePosition(0);
-
Date result = parse(source, pos);
-
-
throw new ParseException("Unparseable date: \"" + source + "\"" ,
-
-
-
-
如果我们把SimpleDateFormat定义成static成员变量,那么多个thread之间会共享这个sdf对象, 所以Calendar对象也会共享。
假定线程A和线程B都进入了parse(text, pos) 方法, 线程B执行到calendar.clear()后,线程A执行到calendar.getTime(), 那么就会有问题。
二. 解决方案
1.方法内部创建SimpleDateFormat,不管是什么时候,将有线程安全的对象由共享变为私有局部变量都可以避免多线程问题,不过也加重了创建对象的负担,虽然随时创建SimpleDateFormat会造成一定的性能影响,而且会对GC产生一定的压力,但这并不是核心问题,只要能产生正确的结果:
-
public static String format(Date date) {
-
-
-
-
return new SimpleDateFormat(YMD_HYPHEN_PATTERN).format(date);
-
2.将SimpleDateFormat进行同步使用,在每次执行时都对其加锁,这样也会影响性能,想要调用此方法的线程就需要block,当多线程并发量比较大时会对性能产生一定影响;
-
public static String formatDate(Date date)throws ParseException{
-
-
-
-
在任何公共的地方使用该类时,都需要对SimpleDateFormat进行加锁。
3.使用ThreadLocal变量,用空间换时间,这样每个线程就会独立享有一个本地的SimpleDateFormat变量;
-
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
-
-
protected DateFormat initialValue() {
-
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
-
-
-
public static Date parse(String dateStr) throws ParseException {
-
return threadLocal.get().parse(dateStr);
-
或者
写一个工具类:
-
-
private static ThreadLocal<SimpleDateFormat> local = new ThreadLocal<SimpleDateFormat>();
-
-
public static Date parse(String str) throws Exception {
-
SimpleDateFormat sdf = local.get();
-
-
sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
-
-
-
-
-
-
public static String format(Date date) throws Exception {
-
SimpleDateFormat sdf = local.get();
-
-
sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
-
-
-
-
-
-
这样就可以保证每个线程的本地变量都是安全的,不同线程之间并不共享相同的SimpleDateFormat,从而避免了线程安全问题。
如果需要对性能比较敏感,可以采用这种方式,至少比前两种的速度要快,但是占用内存也会大一点(但也不会多么夸张)。
分享到:
相关推荐
SimpleDateFormat线程不安全的5种解决方案.md
SimpleDateFormat线程不安全的5种解决方案.docx
NULL 博文链接:https://flynndang.iteye.com/blog/711878
目录SimpleDateFormat诡异bug复现SimpleDateFormat诡异bug字符串日期转Date日期(parse)Date日期转String类型(format)SimpleDateFormat出现bug...ThreadLocal注意事项使用ThreadLocal解决SimpleDateFormat线程安全问题总结...
主要介绍了SimpleDateFormat的线程安全问题与解决方案,非常不错,具有参考借鉴价值,需要的朋友可以参考下
高并发之-SimpleDateFormat类的线程安全问题和解决方案.docx
关于SimpleDateFormat的非线程安全问题及其解决方案.docx
主要介绍了Java SimpleDateFormat线程安全问题原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
Java标准库中的一些类如ArrayList、HashMap和SimpleDateFormat,都是非线程安全的,在多线程环境下直接使用它们可能导致一些非预期的结果,甚至是一些灾难性的结果。一般来说,Java标准库中的类在其API文档中会说明...
深入理解Java:SimpleDateFormat安全的时间格式化
主要介绍了Java多线程环境下SimpleDateFormat类安全转换,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
有关SimpleDateFormat的常用方法说明
JavaScript实现的java.text.SimpleDateFormat。希望多多交流。
日期操作。。。基础的SimpleDateFormat格式化日期!!操作!》初级学习代码
这份软件安全监测报告主要是监测java开发程序中出现的安全问题,找了一个项目程序监测后出现的原版报告显示,在使用DES加解密的情况下,会被检测...还有关于SimpleDateFormat线程不安全的问题,都有详细解释及处理方法
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); date.setTime(time); System.out.println(sdf.format(date)); 发现时间于想要的时间不符,请运行Time.reg文件
由浅入深解析 SimpleDateFormat 由浅入深解析 SimpleDateFormat
SimpleDateFormat使用详解。非常实用!!!!
java 使用SimpleDateFormat类获取系统的当前时间 java 使用SimpleDateFormat类获取系统的当前时间