SimpleDateFormat 类性能问题


SimpleDateFormat类


1.首先了解包结构

java.text.SimpleDateFormat

      -- -java.text.DateFormat

         ----java.text.Format

            ---java.lang.Object

2.常用的方法

  2.1 date (java.util.Date)转 string

 

       SimpleDateFormatdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");

String  str=df.format(new Date());

 

2.2 string 转 date

 

SimpleDateFormat df = newSimpleDateFormat("yyyyMMddHHmmssSSS");

Date date=df. parse (“20140201120202111”);

 

3.线程不安全

  原因:

SimpleDateFormat(下面简称sdf)类内部有一个Calendar对象引用,它用来储存和这个sdf相关的日期信息,例如sdf.parse(dateStr),sdf.format(date)诸如此类的方法参数传入的日期相关String, Date等等,都是交友Calendar引用来储存的.这样就会导致一个问题,如果你的sdf是个static,那么多个thread之间就会共享这个sdf,同时也是共享这个Calendar引用,并且,观察 sdf.parse()方法,你会发现有如下的调用:

DataFormat类中Parse方法调用了一个抽象方法,这里就巧妙的实现了入口统一在父类中,具体使用的方法在子类中实现。

 

 

 

SimpleDateFormat类中具体实现了父类的抽象方法

 

 

这个方法中最重要的代码注意我选中的方法

 

我选中的方法具体代码如下

java.text .CalendarBuilder类路径

 

 

这里会导致的问题就是,如果线程A调用了 sdf.parse(),并且进行了 calendar.clear()后还未执行calendar.getTime()的时候,线程B又调用了sdf.parse(),这时候线程B也执行了sdf.clear()方法,这样就导致线程A的的calendar数据被清空了(实际上A,B的同时被清空了).又或者当 A执行了calendar.clear()后被挂起,这时候B开始调用sdf.parse()并顺利i结束,这样 A calendar内存储的的date变成了后来B设置的calendardate

 

 

 

4.解决方案

 

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.HashMap;

import java.util.Map;

 

/**

 * @author zhenwei.liu created on 2013 13-8-29 下午5:35

 * @version $Id$

 */

public class DateUtil {

 

   /** 锁对象 */

   private static final Object lockObj = new Object();

 

   /** 存放不同的日期模板格式的sdf的Map */

   private static Map<String, ThreadLocal<SimpleDateFormat>>sdfMap = new HashMap<String, ThreadLocal<SimpleDateFormat>>();

 

   /**

     * 返回一个ThreadLocal的sdf,每个线程只会new一次sdf

     *

     * @param pattern

     * @return

     */

   private static SimpleDateFormat getSdf(final String pattern) {

        ThreadLocal<SimpleDateFormat> tl= sdfMap.get(pattern);

 

        // 此处的双重判断和同步是为了防止sdfMap这个单例被多次put重复的sdf

        if (tl == null) {

            synchronized (lockObj) {

                tl = sdfMap.get(pattern);

                if (tl == null) {

                    // 只有Map中还没有这个pattern的sdf才会生成新的sdf并放入map

                   System.out.println("put new sdf of pattern " + pattern +" to map");

 

                    // 这里是关键,使用ThreadLocal<SimpleDateFormat>替代原来直接new SimpleDateFormat

                    tl = newThreadLocal<SimpleDateFormat>() {

 

                        @Override

                        protectedSimpleDateFormat initialValue() {

                           System.out.println("thread: " + Thread.currentThread() +" init pattern: " + pattern);

                            return newSimpleDateFormat(pattern);

                        }

                    };

                    sdfMap.put(pattern, tl);

                }

            }

        }

 

        return tl.get();

   }

 

   /**

     * 是用ThreadLocal<SimpleDateFormat>来获取SimpleDateFormat,这样每个线程只会有一个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) throwsParseException {

        return getSdf(pattern).parse(dateStr);

   }

 

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术分子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值