在使用SimpleDateFormat中有时会遇到由于并发而导致的一些问题,比如java.lang.NumberFormatException,这些原因是由于SimpleDateFormat不是线程安全的,之所以不是线程安全的,是因为类中包含了一个共享变量NumberFormat。可以用ThreadLocal来解决这个问题。
public class Test {
public static void main(String[] args){
for(int i = 0; i < 100; i++){
new Thread(
new Runnable() {
@Override
public void run() {
// No Error
//System.out.println(DateFormatUtil.doFormat(Calendar.getInstance(Locale.CHINA).getTime()));
// Error
//System.out.println(DateFormatUtil.parse("2015-01-01 00:00:00"));
// No Error
System.out.println(DateFormatUtil.parseThreadSafe("2015-01-01 00:00:00"));
}
}
).start();
}
}
}
class DateFormatUtil{
public static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static final ThreadLocal<SimpleDateFormat> formatThreadSafe = new ThreadLocal<SimpleDateFormat>(){
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};
public static String doFormat(Date date){
return format.format(date);
}
public static Date parse(String date){
try {
return format.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
public static Date parseThreadSafe(String date) {
try {
return formatThreadSafe.get().parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
另外,附上一段Spring Security框架中的用法
final class ThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy {
private static final ThreadLocal<SecurityContext> contextHolder = new ThreadLocal();
ThreadLocalSecurityContextHolderStrategy() {
}
public void clearContext() {
contextHolder.remove();
}
public SecurityContext getContext() {
SecurityContext ctx = (SecurityContext)contextHolder.get();
if(ctx == null) {
ctx = this.createEmptyContext();
contextHolder.set(ctx);
}
return ctx;
}
public void setContext(SecurityContext context) {
Assert.notNull(context, "Only non-null SecurityContext instances are permitted");
contextHolder.set(context);
}
public SecurityContext createEmptyContext() {
return new SecurityContextImpl();
}
}