“Great,” you think, “I’ll just create one, static instance, slap it in a field in a DateUtils helper class and life will be good.”
Well, more precisely, life will be good about 97% of the time. A few days after you roll that code into production you’ll discover the second cool fact that’s good to know: SimpleDateFormat is not thread safe. Your code will work just fine most of the time and all of your regression tests will probably pass, but once your system gets under a production load you’ll see the occasional exception.
“Fine,” you think, “I’ll just slap a ’synchronized’ around my use of that one, static instance.”
Ok, fine, you could do that and you’d be more or less ok, but the problem is that you’ve now taken a very common operation (date formatting and parsing) and crammed all of your otherwise-lovely, super-parallel application through a single pipe to get it done.
What would be better is to use a ThreadLocal variable so you can have your cake and eat it, too:
public class DateUtils {
public static final String MY_STANDARD_DATE_FORMAT = "yyyyMMdd";
public static java.util.Date parseDate(String dateString) throws ParseException {
return getFormat().parse(dateString);
}
private static ThreadLocal<DateFormat> format = new ThreadLocal<DateFormat>() {
protected synchronized DateFormat initialValue() {
System.out.println("test");
return new java.text.SimpleDateFormat(MY_STANDARD_DATE_FORMAT);
}
};
private static DateFormat getFormat(){
return (DateFormat) format.get();
}
}
其实这样处理之后还是为每个需要使用线程都分配一个SimpleDateFormat的实例。