Common mistake with Java’s SimpleDateFormat and Calendar in multi-threading environments

Common mistake with SimpleDateFormat and Calendar in multi-threading environments

Sample code from various projects I stumbled upon recently (I skipped some lines that are not relevant to this article):

public class SomeEventSerializer {
protected static final String javaDateFormat = ..
    private static final SimpleDateFormat format = new SimpleDateFormat(javaDateFormat);
    public void serialize(…){
event.getDate() == null ? “-” : format.format(event.getDate()));

Another one:

class SomeResource {
private static SimpleDateFormat format = new SimpleDateFormat(“yyyy-MM-dd”);
public Response loadSomething(…) {
format.parse(startdate);

Another one:

public class SomeActionHelper {
private static final SimpleDateFormat FORMAT_DATE = new SimpleDateFormat(“MM/dd/yyyy”);
public static String getHtml(….) {
StringBuilder builder = new StringBuilder();
builder
.append(FORMAT_DATE.format(string.getStart()))
.append(FORMAT_DATE.format(string.getEnd()));

Javadoc for SimpleDateFormat class states that it is not thread-safe: SimpleDateFormat (Java Platform SE 7 )

Synchronization

Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.

Which means that multiple threads calling FORMAT_DATE.format() will receive corrupted text at random times.

Same with java.util.Calendar, except its javadoc does not say anything about thread-safety.

Possible solutions are:

  • Use Java 8! These problems are solved in JDK8: DateTimeFormatter (Java Platform SE 8 )
  • if you can’t use Java 8 — synchronize access to the formatter.
  • again — if you can’t use Java 8 — use a thread-safe library for date processing like Joda Time.
  • if you can’t use Java 8 and everything else fails — use ThreadLocal (do not do this unless you really understand what you are doing)

In general, whenever you use any class in a multi-threading environment (meaning most of the time really) you should be aware whether or not it is thread-safe. If the class’ javadoc does not explicitly state that the class is thread-safe, it is probably not.

Here is a nicely formatted (no pun intended, gee) explanation with code samples: multithreading — “Java DateFormat is not threadsafe” what does this leads to? — Stack Overflow