`

安全有效地提升simpleDateFormat性能

 
阅读更多

首先看下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) {
// Convert input date to time field list
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`类型的情况。...在实际项目中,合理利用这些技术和最佳实践能够有效地提升软件的质量和稳定性。

    date格式化

    这样的工具类可以避免重复创建`SimpleDateFormat`对象,因为它是线程不安全的,多次实例化可能导致性能问题。 标签中提到了“源码”,意味着我们可能在讨论如何阅读和理解日期格式化的底层实现。`SimpleDateFormat`...

    Java Bug模式详解 pdf版

    9. **线程不安全的类**:书中会列举一些线程不安全的类,如SimpleDateFormat,并提供替代方案,如使用java.time包中的类。 10. **设计模式与重构**:最后,书中可能会提到一些设计模式,如单例模式、工厂模式,以及...

    java api 文档6.0

    - **2D图形增强**:Java 6提升了2D绘图的性能,提供了更多的图形效果和文本渲染功能。 10. **Java应用程序部署**: - **Java Web Start**:改进的Java Web Start技术,使得Java应用程序能够更加轻松地在网络上...

    ireport的打印功能

    总结而言,ireport的打印功能涵盖了从设计到输出的全流程,涉及技术层面的细节较多,开发者应注重代码的健壮性、数据的安全性以及系统的稳定性,同时,不断探索性能优化策略,以提供高效、准确的报表打印服务。

    深入理解高并发编程-Java线程池核心技术

    在深入理解高并发编程,尤其是Java线程池核心技术时,我们首先要明白线程与多线程的概念。线程是操作系统中的基本调度单元,它比进程更小...通过合理使用线程池,我们可以有效地管理线程,减少资源消耗,提升系统效率。

    android and java util

    - **线程和并发**:线程池、锁、并发集合的封装,如ExecutorService和synchronized关键字的使用,能有效提升多线程编程的效率和安全性。 - **泛型**:泛型工具类可以提供类型安全的容器,例如Guava的ImmutableList...

    commons-lang-3-3.1 jar包和源码包

    在3.1版本中,可能包含了一些性能提升、bug修复以及新功能的添加。以下是一些主要的知识点: 1. **字符串处理**:Commons Lang 提供了丰富的字符串操作方法,如StringUtils,它包含了大量的静态方法,用于处理字符...

    Java 55道面试题和答案.docx

    - **SimpleDateFormat非线程安全**:在多线程环境下,使用ThreadLocal封装SimpleDateFormat以保证线程安全,或者使用日期处理库如joda-time。 4. **面向对象和设计原则**: - **SOLID原则**:单一职责、开闭原则...

    java 常用辅助工具类

    在Java编程中,辅助工具类是非常重要的一部分,它们提供了一系列常用的方法,帮助开发者高效地处理各种常见任务。...在实际项目中,根据具体需求选择合适的工具类,可以有效地提升开发效率和代码质量。

    android时间描述的细分

    通过阅读和理解源码,我们可以了解时间处理的原理,学习到如何优化性能,甚至定制自己的时间处理逻辑。例如,`java.time`包中的类在Java 8引入,其设计遵循了JSR 310规范,提供了更加高效和线程安全的实现。 最后,...

    Java工具类

    在Java编程中,工具类(Util Classes)是包含各种实用函数的类,它们不持有状态,主要...在实际应用中,根据项目需求选择合适的加密解密算法、日期时间处理方式以及JSON和XML解析库,能有效提升程序的性能和用户体验。

    日期 字符串截取 格式化 标签

    在IT行业中,日期字符串的截取与格式化是常见的任务,尤其在处理日志、数据分析或者用户界面展示时。这个话题涉及到编程语言...如果你对这个主题有更深入的研究,阅读相关博客、官方文档和源码都是提升技能的有效途径。

    良葛格Java JDK 5.0学习笔记ch02

    9. **集合框架的改进**:包括对集合、队列、映射等接口的优化,以及对ArrayList和HashMap等实现类的性能提升。 10. **日期和时间API的改进**:虽然Java 8引入了全新的日期和时间API,但Java 5.0中也对原有的Date和...

    java实时日志解析处理

    在Java开发中,实时日志解析处理是一项至关重要的任务,特别是在大规模分布式系统或者高并发环境中。日志是系统运行状态的记录,对于故障排查、性能优化、...合理的设计和实现能有效提升系统的监控能力和问题定位效率。

    Java_SE应用部分-34

    自JDK 1.5起,Java引入了泛型,这是一种类型安全的容器机制,允许在编译时检查类型的有效性,并在运行时保持类型信息,从而避免了显式的类型转换。通过泛型,可以创建通用类和方法,如`ArrayList<T>`,其中`T`代表...

    Where-Did-the-Time-Go:时间都去哪儿了 (WDTTG)

    "时间都去哪儿了 (WDTTG)" 这个项目的标题和描述虽然简洁,但我们可以从中推测这可能是一个关于时间...这个项目可能包含了实际的代码示例,用于演示如何在Java中有效地处理时间以及进行性能分析,值得我们深入研究。

    改善Java遗留系统的8个技巧

    通过上述技巧,我们可以有效地改进Java遗留系统的质量和性能。无论是通过使用分析器深入检查应用,还是通过自动化构建和部署简化开发流程,或是通过创建单元测试提高代码质量,每一步都对提升遗留系统的稳定性和可...

    java 快速查询手册(pdf)

    手册还可能包含实战案例,帮助开发者解决实际编程中的问题,如性能优化、调试技巧、错误排查等。此外,对于常见的编程陷阱和最佳实践也会有详尽的讲解。 **附录与资源** "chinaz.com.txt"可能是提供的一些额外链接...

Global site tag (gtag.js) - Google Analytics