Synchronizing access to SimpleDateFormat

22,740

Solution 1

  1. Creating SimpleDateFormat is expensive. Don't use this unless it's done seldom.

  2. OK if you can live with a bit of blocking. Use if formatDate() is not used much.

  3. Fastest option IF you reuse threads (thread pool). Uses more memory than 2. and has higher startup overhead.

For applications both 2. and 3. are viable options. Which is best for your case depends on your use case. Beware of premature optimization. Only do it if you believe this is an issue.

For libraries that would be used by 3rd party I'd use option 3.

Solution 2

The other option is Commons Lang FastDateFormat but you can only use it for date formatting and not parsing.

Unlike Joda, it can function as a drop-in replacement for formatting. (Update: Since v3.3.2, FastDateFormat can produce a FastDateParser, which is a drop-in thread-safe replacement for SimpleDateFormat)

Solution 3

If you are using Java 8, you may want to use java.time.format.DateTimeFormatter:

This class is immutable and thread-safe.

e.g.:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String str = new java.util.Date().toInstant()
                                 .atZone(ZoneId.systemDefault())
                                 .format(formatter);

Solution 4

Commons Lang 3.x now has FastDateParser as well as FastDateFormat. It is thread safe and faster than SimpleDateFormat. It also uses the same format/parse pattern specifications as SimpleDateFormat.

Solution 5

Don't use SimpleDateFormat, use joda-time's DateTimeFormatter instead. It is a bit stricter in the parsing side and so isn't quite a drop in replacement for SimpleDateFormat, but joda-time is much more concurrent friendly in terms of safety and performance.

Share:
22,740
3urdoch
Author by

3urdoch

Java webapp developer

Updated on March 16, 2020

Comments

  • 3urdoch
    3urdoch about 4 years

    The javadoc for SimpleDateFormat states that SimpleDateFormat is not synchronized.

    "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."

    But what is the best approach to using an instance of SimpleDateFormat in a multi threaded environment. Here are a few options I have thought of, I have used options 1 and 2 in the past but I am curious to know if there are any better alternatives or which of these options would offer the best performance and concurrency.

    Option 1: Create local instances when required

    public String formatDate(Date d) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(d);
    }
    

    Option 2: Create an instance of SimpleDateFormat as a class variable but synchronize access to it.

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    public String formatDate(Date d) {
        synchronized(sdf) {
            return sdf.format(d);
        }
    }
    

    Option 3: Create a ThreadLocal to store a different instance of SimpleDateFormat for each thread.

    private ThreadLocal<SimpleDateFormat> tl = new ThreadLocal<SimpleDateFormat>();
    public String formatDate(Date d) {
        SimpleDateFormat sdf = tl.get();
        if(sdf == null) {
            sdf = new SimpleDateFormat("yyyy-MM-hh");
            tl.set(sdf);
        }
        return sdf.format(d);
    }