ThreadLocal解决SimpleDateFormat问题

    大致意思:Tim Cull碰到一个SimpleDateFormat带来的严重的性能问题,该问题主要有SimpleDateFormat引发,创建一个 SimpleDateFormat实例的开销比较昂贵,解析字符串时间时频繁创建生命周期短暂的实例导致性能低下。即使将 SimpleDateFormat定义为静态类变量,貌似能解决这个问题,但是SimpleDateFormat是非线程安全的,同样存在问题,如果用 ‘synchronized’线程同步同样面临问题,同步导致性能下降(线程之间序列化的获取SimpleDateFormat实例)。

     Tim Cull使用Threadlocal解决了此问题,对于每个线程SimpleDateFormat不存在影响他们之间协作的状态,为每个线程创建一个SimpleDateFormat变量的拷贝或者叫做副本,代码如下:

package ThreadLocalTest;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtil {

	private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
	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方法,主要作用是创建时初始化实例。也可以采用下面方式创建;

package ThreadLocalTest;

import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class DateUtil1 {

    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;
    }
}

测试

package ThreadLocalTest;

import java.text.DateFormat;
import java.util.Date;

public class Test {
	public static void main(String[] args) {
		 DateFormat dt = DateUtil.getDateFormat();
 		System.out.println(dt.format(new Date()));
 	}
}

输出

2016-08-25 11:30:07

以上转自链接:这这 


还有一个封装的比较好的代码~

package ThreadLocalTest;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class DateUtil3 {

	 /** 存放不同的日期模板格式的sdf的Map */
	  private static ThreadLocal<Map<String, SimpleDateFormat>> sdfMap = new ThreadLocal<Map<String, SimpleDateFormat>>() {
	    @Override
	    protected Map<String, SimpleDateFormat> initialValue() {
	      System.out.println(Thread.currentThread().getName()	+ " init pattern: " + Thread.currentThread());
	      return new HashMap<String, SimpleDateFormat>();
	    }
	  };

	  /**
	   * 返回一个SimpleDateFormat,每个线程只会new一次pattern对应的sdf
	   *
	   * @param pattern
	   * @return
	   */
	  private static SimpleDateFormat getSdf(final String pattern) {
	    Map<String, SimpleDateFormat> tl = sdfMap.get();
	    SimpleDateFormat sdf = tl.get(pattern);
	    if (sdf == null) {
	      System.out.println(Thread.currentThread().getName()+" put new sdf of pattern " + pattern + " to map");
	      sdf = new SimpleDateFormat(pattern);
	      tl.put(pattern, sdf);
	    }
	    return sdf;
	  }

	  /**
	   * 这样每个线程只会有一个SimpleDateFormat
	   *
	   * @param date
	   * @param pattern
	   * @return
	   */
	  public static String format(Date date, String pattern) {
	    return getSdf(pattern).format(date);
	  }

	  public static Date parse(String dateStr, String pattern)
	      throws ParseException {
	    return getSdf(pattern).parse(dateStr);
	  }
}

代码来源此

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值