前言:
SimpleDateFormat不是线程安全的,而且创建一个实例的开销是非常昂贵,解析字符串时间时频繁创建生命周期短暂的实例导致性能低下。
SimpleDateFormat的javadoc中有这么句话:
Synchronization
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.
翻译一下:
*日期格式是不同步的.
* 建议为每个线程创建独立的格式实例.
* 如果多线程并发访问同一个格式,则必须保持外部同步.
目前很多公司使用的是一下两种方式去创建的日期工具类:
1、在每个方法里面使用new SimpleDateFormat的形式
public static Date newParse(String strDate) throws ParseException { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(strDate); }
注:这种方式是能解决线程安全问题,但是产生了性能问题,主要是创建一个 SimpleDateFormat实例的开销比较昂贵,解析字符串时间时频繁创建生命周期短暂的实例导致性能低下。
2、定义一个全局变量
private static final SimpleDateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); /** * 格式化日期与时间 */ public static String formatDatetime(long timestamp) { return datetimeFormat.format(new Date(timestamp)); }
注:这种方式是解决了性能问题,但是没有解决线程安全问题,在多线程环境下,容易发生各种意想不到的问题,如:java.lang.NumberFormatException: multiple points或者java.lang.NumberFormatException: For input string: ""等异常。
解决此问题有两种方式:
1、使用Threadlocal
private static final ThreadLocal<SimpleDateFormat> _threadLocal = new ThreadLocal<SimpleDateFormat>() { protected SimpleDateFormat initialValue() { return new SimpleDateFormat(); } }; /** * 格式化日期与时间 */ public static String formatDatetime(long timestamp) { return _threadLocal.get().format(new Date(timestamp)); }
2、使用享元模式
A、创建SimpleDateFormatFactory类
public class SimpleDateFormatFactory { private static final ThreadLocal<Map<String, SimpleDateFormat>> _threadLocal = new ThreadLocal<Map<String, SimpleDateFormat>>() { protected Map<String, SimpleDateFormat> initialValue() { return new HashMap<String, SimpleDateFormat>(); } }; public static SimpleDateFormat getInstance() { return getInstance(DateUtil.DATE_FORMAT); } public static SimpleDateFormat getInstance(String format) { SimpleDateFormat sdf = _threadLocal.get().get(format); if (null == sdf) { sdf = new SimpleDateFormat(format); _threadLocal.get().put(format, sdf); } return sdf; } }
B、DateUtil类
public class DateUtil { /** * 显示日期的格式,yyyy-MM-dd */ public static final String DATE_FORMAT = "yyyy-MM-dd"; /** * DateFormat,格式:yyyy-MM-dd */ private static DateFormat dateFormat; static { dateFormat = SimpleDateFormatFactory.getInstance(DATE_FORMAT); } /** * 格式化日期与时间 */ public static String formatDatetime(long timestamp) { return dateFormat.format(new Date(timestamp)); } }
优点:可以更好的去减少系统中对象的个数和对外部状态相对独立等好处。
相关推荐
目录SimpleDateFormat诡异bug复现SimpleDateFormat诡异bug字符串日期转Date日期(parse)Date日期转String类型(format)SimpleDateFormat出现bug...ThreadLocal注意事项使用ThreadLocal解决SimpleDateFormat线程安全问题总结...
SimpleDateFormat线程不安全的5种解决方案.md
SimpleDateFormat线程不安全的5种解决方案.docx
NULL 博文链接:https://flynndang.iteye.com/blog/711878
主要介绍了SimpleDateFormat的线程安全问题与解决方案,非常不错,具有参考借鉴价值,需要的朋友可以参考下
高并发之-SimpleDateFormat类的线程安全问题和解决方案.docx
关于SimpleDateFormat的非线程安全问题及其解决方案.docx
主要介绍了Java SimpleDateFormat线程安全问题原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
Java标准库中的一些类如ArrayList、HashMap和SimpleDateFormat,都是非线程安全的,在多线程环境下直接使用它们可能导致一些非预期的结果,甚至是一些灾难性的结果。一般来说,Java标准库中的类在其API文档中会说明...
深入理解Java:SimpleDateFormat安全的时间格式化
主要介绍了Java多线程环境下SimpleDateFormat类安全转换,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
这份软件安全监测报告主要是监测java开发程序中出现的安全问题,找了一个项目程序监测后出现的原版报告显示,在使用DES加解密的情况下,会被检测...还有关于SimpleDateFormat线程不安全的问题,都有详细解释及处理方法
有关SimpleDateFormat的常用方法说明
JavaScript实现的java.text.SimpleDateFormat。希望多多交流。
日期操作。。。基础的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类获取系统的当前时间