How to know if a Java SE class or method is thread safe?
- For a standard Java SE class, the best way to know whether or not the class is thread-safe is to carefully read its documentation. Always read both the class documentation and the method documentation. If either say it's not synchronized or not thread-safe, you know it's not thread-safe.
Therefore, the
DateFormat
class is not thread safe. The documentation specifically says: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.
Declaring a field
private
does not make your implementation thread-safe.private
merely says that outside classes can't see that field. Let's look at your method:for (int i=0;i<10;i++) new Thread(new Runnable(){ public void run(){ System.out.println(df.format(date)); } });
The
Runnable
objects that you create are anonymous classes. Anonymous classes are inner classes, which have access to private fields of their surrounding class. If it wasn't so, your program would not compile - they could not access thedf
field.But they can. So in fact you are having 10 threads that are all accessing your one
DateFormat
object, referred to bydf
. Since we already know thatDateFormat
is not thread-safe, your program is not thread-safe.- Furthermore, if two external threads have references to your object (I mean the object that has the
df
inside it. You didn't give the class declaration so I don't know what its name is). They have references to the same instance of your class. If both of them callformat
at the same time, both will be runningDateFormat.format
using the same privatedf
. Thus, this is not going to be thread-safe. - To be thread-safe, you need to synchronize on the object or use some other kind of lock (one lock for all the possible threads that access it), which is exactly what the documentation said to do.
- Another way is to have a completely local object, which is visible to only one thread. Not a field - a local variable, which has access to a uniquely created instance of
DateFormat
(so you have a new copy every time you call the method). Beware of anonymous classes, though! In your example, even ifdf
was a local field to theformat
method, it would still not be thread-safe because all your threads would be accessing the same copy.
As per the docs, it is stated that the format is not thread safe.
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.
Date format
How to read this ? If you don't have explicit guarantee that some method is thread safe(or its documented as unsafe) then you cannot make any assumptions about it being safe.
However, if you really wish to only use single method which might not be statefull, you can always create high concurrency environment and test for data integrity with and without synchronization.
I have had similar question to this, with Ciphers and RSA. The answer there shows one way how to test specific method of java SE class in general for this. Note however that implementation could change at any point, and by making your own implementation against implementation details rather then interface might cause some unpredictable issues in the future.
testing for data integrity
I know it is hard to believe, but DateFormat.format() actually modifies the DateFormat's state. For instance, for SimpleDateFormat:
// Called from Format after creating a FieldDelegate
private StringBuffer format(Date date, StringBuffer toAppendTo,
FieldDelegate delegate) {
// Convert input date to time field list
calendar.setTime(date);
where calendar
is a field of DateFormat.
Therefore, I can only recommend you trust the documentation. It may know things you don't.