SimpleDateFormat is not thread safe. When it is used in multithreaded applications, like Java web containers, it's forbidden use it as a static constant
public static final DateFormat DATE_FORMAT = new SimpleDateFormat('YYYY.MM.dd'); // DON'T!
Most developers properly constructs new SimpleDateFormat everytime they needDateFormat dateFormat = new SimpleDateFormat('YYYY.MM.dd');
String str = dateFormat.format(date);
However, constructing new SimpleDateFormat is not so cheap operation. So, how to safe CPU and memory like in static final pattern in a multithreaded environment?Solution 1: clone
Fortunatelly,
SimpleDateFormat implements clone() method, which is fasters than constructing a new one form a String:
private static final DateFormat DATE_FORMAT_TEMPLATE = new SimpleDateFormat('YYYY.MM.dd'); // Do not use directly
/**
* @return every time a new SimpleDateFormat.
*/
public static DateFormat getDateFormat() {
return DATE_FORMAT_TEMPLATE.clone();
}
Solution 2: ThreadLocal
A general solution for sharing non-thread safe objects is to have one copy for each thread. Java has a very nice
ThreadLocal. Together with lazy initialization we got the proper thread safe and fast solution:
private static final ThreadLocal DATE_FORMAT_TL = new ThreadLocalThis solution has advantage over() { protected DateFormat initialValue() { return new SimpleDateFormat('YYYY.MM.dd'); }; }; /** * @return SimpleDateFormat, new one for every thread. */ public static DateFormat getDateFormat() { return DATE_FORMAT_TL .get(); } /** * Simple, optimized Date formatting. */ public static String format(Date d) { return format == null ? null : getDateFormat().format(d); }
clone() method, that calling getDateFormat() multiple times in one thread (e.g. inside a loop) does not create a new object. I like to add format() to simplify usage and handle null values.
Note: ThreadLocal may cause redeploy memory leaks when it's value from a WAR class. E.g. see Java Web Container: Hunting Redeploy Memory Leaks
Žádné komentáře:
Okomentovat