Google

Jul 3, 2012

Java coding question and answer on multi-threading

Core Java Coding Questions and Answers for beginner to intermediate level

Q1 Q2 Q3 Q4 Q5 Q6

Q. Can you review the given code and provide your feedback?

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtil {
 
 SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
 
 public String formatDate(Date input) {
      return sdf.format(input);
 }
 
}
A.

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 ThreadLocal<simpledateformat> tl = new ThreadLocal<simpledateformat>() {
  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?

Labels: ,

4 Comments:

Anonymous Anonymous said...

Thank you for your wonderful work.

Here is my attempt at solution 3:


public class ThreadSafeSimpleDateFormat extends DateFormat
{
private static final long serialVersionUID = 1L;

private static ThreadLocal tl =
new ThreadLocal()
{
protected SimpleDateFormat initialValue()
{
return new SimpleDateFormat("MM/dd/yyyy");
}
};

@Override
public StringBuffer format(Date date, StringBuffer toAppendTo,
FieldPosition fieldPosition)
{
return tl.get().format(date, toAppendTo, fieldPosition);
}

@Override
public Date parse(String source, ParsePosition pos)
{
return tl.get().parse(source, pos);
}

}

4:57 AM, August 05, 2012  
Blogger Unknown said...

thank u for giving nice explanation..

i have few doubts on solution 2....
why do we need to use static variable for simpledateformat, why don't we use a class variable instead.


and here is my ans about solution 3

it just same as solution 1,
only change is that, instead of using SimpleDateFormat class, we have to write one new class by extending the simpledateformat class as follows

Class ThreadSafeSimpleDateFormat extends SimpleDateFormat
{
public synchronized String format(Date x)
{
return super.format(x);
}
}


is this correct?

3:53 AM, January 03, 2013  
Anonymous Anonymous said...

Prefer composition to inheritance. I suggest using a local SimpleDateFormat variable in your decorator instead of extending from it.

1:05 PM, January 23, 2013  
Blogger Unknown said...

Yes. Favor composition.

10:40 PM, November 03, 2013  

Post a Comment

Subscribe to Post Comments [Atom]

<< Home