Wednesday, May 24, 2023

SimpleDateFormat in Java is not Thread-Safe Use Carefully

SimpleDateFormat in Java is a very common class and often used to format Date to String and parse String into Date in Java, especially in pre Java 8 world, but it can cause very subtle and hard to debug issues if not used carefully because both DateFormat and SimpleDateFormat both are not thread-safe and buggy. A call to format() and parse() method mutate the state of DateFormat class and should be synchronized externally in order to avoid any issue but many Java developers are not aware of these. That's why it's better to completely avoid using SimpleDateFormat class especially if you are using Java Se 8 or higher version like Java SE 11 or Java SE 17. here are a few points which you should take care while using SimpleDateFormat in Java:



SimpleDateFormat in Java is not Thread-Safe

1) Use local DateFormat or SimpleDateFormat objects for converting or formatting dates in Java. Making them local ensure that they will not be shared between multiple Threads.

2) If you are sharing Date for SimpleDateFormat class in Java then you need to externally synchronize call to format() and parse() method as they mutate the state of DateFormat object and can create subtle and hard to fix bugs while formatting Strings or creating dates in Java. The best is to avoid sharing of DateFormat class altogether.

3) If you have the option use the JODA date time library for your date and time-related operation. it's easy to understand and portable with Java Date API and solves all thread-safety issues associated with SimpleDateFormat in Java.

4) Another good alternative of SimpleDateFormat in Java is Apaches' commons.lang package which holds a class called  FastDateFormat utility class and thread-safe alternative of SimpleDateFormat in Java.

5) Another approach of synchronizing DateFormat and SimpleDateFormat is using ThreadLocal, which creates SimpleDateFormat on a per Thread basis but it can be a source of severe memory leak and java.lang.OutOfMemoryError if not used carefully. so avoid until you don't have any other option.

And, if you like a list, here are 10 reasons why you should not be using SimpleDateFormat class in Java anymore, especially after Java SE 8 release:

10 Reasons to not use SimpleDateFormat in Java



That’s all on SimpleDateFormat in Java. Many people have pointed out flaws in the design of the Format class but unfortunately, Sun or Oracle has not addressed them in any release not even in JDK7. SimpleDateFormat is still the first choice because of its availability on standard libraries but should be used carefully.


Other Java tutorials you may like

P. S. - Things have changed from Java 8 onwards and you have a better Date and Time API with new classes for everything related to date and time, including formatting. If you are running on Java 8 or higher version then you should use DateTimeFormatter class to format the Date String in Java. They are both Immutable and Thread-safe. 

12 comments :

Ricardo Zuasti said...

Nice one, didn't know about this and indeed it can be *very* relevant. Oracle should really address this ASAP, SimpleDateFormat is widely used in multi-threaded apps...

I guess there is no reason to use it over FastDateFormat.

Stéphan Mestach said...

I've simply dropped jdk date classes in favor to jodatime from all our java projects enforcing this rule
with sonar :

http://mestachs.wordpress.com/2012/03/17/dangerous-can-be-dating-in-java-joda-to-the-rescue/

Javin @ serialization interview questions said...

Thanks for your comment Stephan. Indeed many people uses JodaTime in place of SimpleDateFormat in Java. those who stick around only because of not introducing new library.

Javin @ multi-threading interview question said...

@Recordo, Thanks for your comments. If Oracle can make SimpleDateFormat better and bug free that would be best. Instead of introducing lot of new library in JDK7, they could have just address this as well.

Anonymous said...

Note that even if you do synchronize externally to use SimpleDateFormat in a multi-threaded environment, there's no way to serialize a SimpleDateFormat in a thread-safe way, because it holds a reference to a Calendar, which mutates its internal state during de-/serialization
(see Calendar#writeObject and Calendar#readObject, the 'zone' field is changed).

Javin @ serialization interview questions said...

Good point @Anonymous. Thanks for bringing point of Serialization on SimpleDateFormat.

Daniel Schneller said...

This is a topic Oracle/Sun are probably never going to address. I wrote about it 5 years ago http://www.danielschneller.com/2007/04/calendar-dateformat-and-multi-threading.html and still there is no change. If you do not want to move to Joda (or can't), around the same time I contributed a detector to FindBugs that looks for static fields of type DateFormat or Calendar (and their respective subclasses) and issues a warning in the thread-safety category. Make sure to have FindBugs run and check this and other stuff in your build process.

Javin @ HashMap vs HashSet said...

@Daniel, Thanks for your comment. you may be right because its known issue from long time. many of programmer have stopped using SimpleDateFormat due to its thread-safety issue and as you mentioned static code analyzer also has pattern for detecting static SimpleDateFormat among code. It's just unfortunate Sun doesn't address it.

Anonymous said...

Can anyone give a working code example for "call to format() and parse() method should be synchronized externally"? It would be a huge help for novices like me.

Javin @ blocking method in java said...

@Anonymous, It would be similar to how you synchronize shared object for mutual exclusion. here is a psuedo code

DateFormat localFormat; //shared
synchronized(localFormat){
localFormat.format();
}

Unknown said...

Commons Lang 3.x now has FastDateParser and FastDateFormat. These classes are thread safe and faster than SimpleDateFormat. They also support the same format/parse pattern specifications as SimpleDateFormat.

El Santo said...

ThreadLocal + SimpleDateFormat = SimpleDateFormatThreadSafe

https://gist.github.com/pablomoretti/9748230

Post a Comment