The DateFormat class is used in Java multithreaded programming

  • 2020-04-01 03:57:57
  • OfStack

  The DateFormat class is a non-thread-safe class. (link: http://download.oracle.com/javase/6/docs/api/java/text/DateFormat.html) document mentioned "the Date formats are not synchronized. We recommend creating a separate date format for each thread. If multiple threads access a date format at the same time, this requires external synchronization blocks.

The following code shows how to use DateFormat to convert string dates into date objects in a threaded environment. It is more efficient to create an instance to retrieve the date format, because the system does not need to retrieve the local language and country multiple times.
 


public class DateFormatTest {
 
 private final DateFormat format =
      new SimpleDateFormat("yyyyMMdd");
 
 public Date convert(String source)
           throws ParseException{
  Date d = format.parse(source);
  return d;
 }
}

This code is non-thread-safe. We can call it from multiple threads. In the code called below, I created a thread pool with two threads and submitted five date conversion tasks before viewing the results of the run:
 


final DateFormatTest t =new DateFormatTest();
Callable<Date> task =new Callable<Date>(){
  public Date call()throws Exception {
    return t.convert("20100811");
  }
};
 
//Let's try the two-thread case
ExecutorService exec = Executors.newFixedThreadPool(2);
List<Future<Date>> results =
       new ArrayList<Future<Date>>();
 
//Implement 5 date conversions
for(int i =0; i <5; i++){
  results.add(exec.submit(task));
}
exec.shutdown();
 
//View the results
for(Future<Date> result : results){
  System.out.println(result.get());
}

The code doesn't work as we'd like it to - sometimes it prints the correct date, sometimes it prints the wrong one (for example.sat Jul 31 00:00:00 BST 2012), and sometimes it even throws a NumberFormatException!


How to use the DateFormat class concurrently

There are several ways to use the DateFormat class in thread-safe situations.

1. The synchronous

The easiest way to do this is to lock the DateFormat object before doing the date conversion. This approach allows only one thread to access the DateFormat object at a time, while other threads wait.
 


public Date convert(String source)
          throws ParseException{
 synchronized(format) {
  Date d = format.parse(source);
  return d;
 }
}


2. Using ThreadLocal

Another approach is to use the ThreadLocal variable to hold the DateFormat object, which means that each thread has its own copy and doesn't have to wait for another thread to release it. This approach is more efficient than using synchronized blocks.
 


public class DateFormatTest {
 
 private static final ThreadLocal<DateFormat> df
         = new ThreadLocal<DateFormat>(){
  @Override
  protected DateFormat initialValue() {
    return new SimpleDateFormat("yyyyMMdd");
  }
 };
 
 public Date convert(String source)
           throws ParseException{
  Date d = df.get().parse(source);
  return d;
 }
}

3. Joda - Time

Joda-time is a great open-source alternative to the JDK's date and calendar API, whose DateTimeFormat is thread-safe and immutable.

 


import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.util.Date;
 
public class DateFormatTest {
 
 private final DateTimeFormatter fmt =
    DateTimeFormat.forPattern("yyyyMMdd");
 
 public Date convert(String source){
  DateTime d = fmt.parseDateTime(source);
  returnd.toDate();
 }
}



Related articles: