大体意思:Tim Cull碰到一个SimpleDateFormat带来的严重的性能问题,该问题主要有SimpleDateFormat引起,建立一个 SimpleDateFormat实例的开销比较昂贵,解析字符串时间时频繁建立生命周期短暂的实例致使性能低下。即便将 SimpleDateFormat定义为静态类变量,貌似能解决这个问题,可是SimpleDateFormat是非线程安全的,一样存在问题,若是用 ‘synchronized’线程同步一样面临问题,同步致使性能降低(线程之间序列化的获取SimpleDateFormat实例)。java
Tim Cull使用Threadlocal解决了此问题,对于每一个线程SimpleDateFormat不存在影响他们之间协做的状态,为每一个线程建立一个SimpleDateFormat变量的拷贝或者叫作副本,代码以下:apache
import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * 使用ThreadLocal以空间换时间解决SimpleDateFormat线程安全问题。 */ 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线程安全问题 */ public class DateUtil { private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; private static ThreadLocal threadLocal = new ThreadLocal(); // 第一次调用get将返回null // 获取线程的变量副本,若是不覆盖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 }
固然也可使用:spa
apache commons-lang包的DateFormatUtils或者FastDateFormat实现,apache保证是线程安全的,而且更高效。线程