首先看下JDK原始文档SimpleDateFormat的描述:
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.
因此SimpleDateFormat带来的严重的性能问题,创建一个 SimpleDateFormat实例的开销比较昂贵,解析字符串时间时频繁创建生命周期短暂的实例导致性能低下。即使将 SimpleDateFormat定义为静态类变量,貌似能解决这个问题,但是SimpleDateFormat是非线程安全的,同样存在问题,如果用 ‘synchronized’线程同步同样面临问题,同步导致性能下降(线程之间序列化的获取SimpleDateFormat实例)。
为什么创建一个simpleDateFormat会花费很大的代价了?
note that performance is bad because SimpleDateFormat has a calendar instance as a member and it is allocation of
the calendar object that is expensive. This is also why it isn’t thread safe –
if
2
threads change the calendar da
te or timezone or something at once the formats returned will be inconsistent.
上面的解释在于simpleDateFormat有一个calender的实例变量,分配这个变量的代价是昂贵的。这也是为什么它不是线程安全的原因了,如果2个线程同时修改了这个calendar的时间信息,那么format的输出自然是不正确的。
private
StringBuffer format(Date date, StringBuffer toAppendTo,
FieldDelegate delegate) {
calendar.setTime(date);
为了解决线程安全问题可以使用ThreadLocal,使用如下:
第一种方式:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 使用ThreadLocal以空间换时间解决SimpleDateFormat线程安全问题。
*
* @author
*
*/
public class DateUtil {
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
@SuppressWarnings("rawtypes")
private static ThreadLocal threadLocal = new ThreadLocal() {
protected synchronized Object initialValue() {
return new SimpleDateFormat(DATE_FORMAT);
}
};
public static DateFormat getDateFormat() {
return (DateFormat) threadLocal.get();
}
public static Date parse(String textDate) throws ParseException {
return getDateFormat().parse(textDate);
}
}
创建一个ThreadLocal类变量,这里创建时用了一个匿名类,覆盖了initialValue方法,主要作用是创建时初始化实例。
第二种方式:
import java.text.DateFormat;
import java.text.SimpleDateFormat;
/**
* 使用ThreadLocal以空间换时间解决SimpleDateFormat线程安全问题。
*
* @author
*
*/
public class DateUtil {
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
// 第一次调用get将返回null
private static ThreadLocal threadLocal = new ThreadLocal();
// 获取线程的变量副本,如果不覆盖initialValue,第一次get返回null,故需要初始化一个SimpleDateFormat,并set到threadLocal中
public static DateFormat getDateFormat() {
DateFormat df = (DateFormat) threadLocal.get();
if (df == null) {
df = new SimpleDateFormat(DATE_FORMAT);
threadLocal.set(df);
}
return df;
}
}
我们看下我们覆盖的initialValue方法:
protected T initialValue() {
return null;//直接返回null
}
第三种方式:
apache commons-lang包的DateFormatUtils或者FastDateFormat实现,apache保证是线程安全的,并且更高效。
分享到:
相关推荐
### 字符串转日期知识点详解 #### 一、概述 在日常开发工作中,我们经常会遇到需要将日期格式的字符串转换为`Date`类型的情况。...在实际项目中,合理利用这些技术和最佳实践能够有效地提升软件的质量和稳定性。
这样的工具类可以避免重复创建`SimpleDateFormat`对象,因为它是线程不安全的,多次实例化可能导致性能问题。 标签中提到了“源码”,意味着我们可能在讨论如何阅读和理解日期格式化的底层实现。`SimpleDateFormat`...
9. **线程不安全的类**:书中会列举一些线程不安全的类,如SimpleDateFormat,并提供替代方案,如使用java.time包中的类。 10. **设计模式与重构**:最后,书中可能会提到一些设计模式,如单例模式、工厂模式,以及...
- **2D图形增强**:Java 6提升了2D绘图的性能,提供了更多的图形效果和文本渲染功能。 10. **Java应用程序部署**: - **Java Web Start**:改进的Java Web Start技术,使得Java应用程序能够更加轻松地在网络上...
在深入理解高并发编程,尤其是Java线程池核心技术时,我们首先要明白线程与多线程的概念。线程是操作系统中的基本调度单元,它比进程更小...通过合理使用线程池,我们可以有效地管理线程,减少资源消耗,提升系统效率。
- **线程和并发**:线程池、锁、并发集合的封装,如ExecutorService和synchronized关键字的使用,能有效提升多线程编程的效率和安全性。 - **泛型**:泛型工具类可以提供类型安全的容器,例如Guava的ImmutableList...
在3.1版本中,可能包含了一些性能提升、bug修复以及新功能的添加。以下是一些主要的知识点: 1. **字符串处理**:Commons Lang 提供了丰富的字符串操作方法,如StringUtils,它包含了大量的静态方法,用于处理字符...
- **SimpleDateFormat非线程安全**:在多线程环境下,使用ThreadLocal封装SimpleDateFormat以保证线程安全,或者使用日期处理库如joda-time。 4. **面向对象和设计原则**: - **SOLID原则**:单一职责、开闭原则...
在Java编程中,辅助工具类是非常重要的一部分,它们提供了一系列常用的方法,帮助开发者高效地处理各种常见任务。...在实际项目中,根据具体需求选择合适的工具类,可以有效地提升开发效率和代码质量。
通过阅读和理解源码,我们可以了解时间处理的原理,学习到如何优化性能,甚至定制自己的时间处理逻辑。例如,`java.time`包中的类在Java 8引入,其设计遵循了JSR 310规范,提供了更加高效和线程安全的实现。 最后,...
在Java编程中,工具类(Util Classes)是包含各种实用函数的类,它们不持有状态,主要...在实际应用中,根据项目需求选择合适的加密解密算法、日期时间处理方式以及JSON和XML解析库,能有效提升程序的性能和用户体验。
在IT行业中,日期字符串的截取与格式化是常见的任务,尤其在处理日志、数据分析或者用户界面展示时。这个话题涉及到编程语言...如果你对这个主题有更深入的研究,阅读相关博客、官方文档和源码都是提升技能的有效途径。
9. **集合框架的改进**:包括对集合、队列、映射等接口的优化,以及对ArrayList和HashMap等实现类的性能提升。 10. **日期和时间API的改进**:虽然Java 8引入了全新的日期和时间API,但Java 5.0中也对原有的Date和...
在Java开发中,实时日志解析处理是一项至关重要的任务,特别是在大规模分布式系统或者高并发环境中。日志是系统运行状态的记录,对于故障排查、性能优化、...合理的设计和实现能有效提升系统的监控能力和问题定位效率。
自JDK 1.5起,Java引入了泛型,这是一种类型安全的容器机制,允许在编译时检查类型的有效性,并在运行时保持类型信息,从而避免了显式的类型转换。通过泛型,可以创建通用类和方法,如`ArrayList<T>`,其中`T`代表...
"时间都去哪儿了 (WDTTG)" 这个项目的标题和描述虽然简洁,但我们可以从中推测这可能是一个关于时间...这个项目可能包含了实际的代码示例,用于演示如何在Java中有效地处理时间以及进行性能分析,值得我们深入研究。
通过上述技巧,我们可以有效地改进Java遗留系统的质量和性能。无论是通过使用分析器深入检查应用,还是通过自动化构建和部署简化开发流程,或是通过创建单元测试提高代码质量,每一步都对提升遗留系统的稳定性和可...
手册还可能包含实战案例,帮助开发者解决实际编程中的问题,如性能优化、调试技巧、错误排查等。此外,对于常见的编程陷阱和最佳实践也会有详尽的讲解。 **附录与资源** "chinaz.com.txt"可能是提供的一些额外链接...