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设置的calendar的date
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
/**
* 返回一个ThreadLocal的sdf,每个线程只会new一次sdf
*
* @param pattern
* @return
*/
private static SimpleDateFormat getSdf(final String pattern) {
ThreadLocal
// 此处的双重判断和同步是为了防止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
tl = newThreadLocal
@Override
protectedSimpleDateFormat initialValue() {
System.out.println("thread: " + Thread.currentThread() +" init pattern: " + pattern);
return newSimpleDateFormat(pattern);
}
};
sdfMap.put(pattern, tl);
}
}
}
return tl.get();
}
/**
* 是用ThreadLocal
*
* @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);
}
}