Q. Can you review the given code and provide your feedback?
import java.text.SimpleDateFormat;A.
import java.util.Date;
public class DateUtil {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
public String formatDate(Date input) {
return sdf.format(input);
}
}
1. The code does not fail fast by checking for the preconditions.
2. The above code is not thread-safe as the SimpleDateFormat class is not thread-safe. If you check the API documentation, you will see
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.
Here is the illustration of the thread-safety issue with instance variables and the objects they point to having methods not being synchronized.
As you could see, multiple threads are accessing the single instance of the "SimpleDateFormat" object via the reference "sdf". Since the methods in the SimpleDateFormat class are not properly synchronized, they are not thread-safe.
The thread-safety issue can be resolved a number of ways.
Solution 1: Here is the thread safe code.
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil {
private static final String SIMPLE_FORMAT = "dd/MM/yyyy";
public String formatDate(Date input) {
if(input == null){
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat(SIMPLE_FORMAT);//local variable
return sdf.format(input);
}
}
Here is the illustration of solution 1.
As you could see, the local variables are thread-safe as each stack will have its own "sdf" reference. The objects are always created in the heap.
Solution 2: While the solution 1 is thread-safe, it will end up creating too many SimpleDateFormat objects in the heap if a single thread invokes the formatDate(Date input) method multiple times. This can be overcome by creating the SimpleDateFormat objects as "per thread singleton" with the ThreadLocal class.
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil {
// anonymous inner class. Each thread will have its own copy of the SimpleDateFormat
private final static ThreadLocaltl = new ThreadLocal () {
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("dd/MM/yyyy");
}
};
public String formatDate(Date input) {
if (input == null) {
return null;
}
return tl.get().format(input);
}
}
Learn more: Java multi-threading interview questions and answers: atomic operations
Solution 3: If "SimpleDateFormat" were your own class, you could have appropriately made it thread-safe , for instance by applying method level or block level synchronization. Since, it is a third party library, you could use a decorator design pattern to wrap the SimpleDateFormat in a new class say SimpleDateFormatWrapper. The SimpleDateFormatWrapper will be made thread-safe.
Can someone write the code for the Solution 3?