5/20/2009

ThreadSafeDateFormat

Problem
As known, Java class SimpleDateFormat is not Thread-safe.
It means that you cannot declare a static member DateFormat in class:

private static final DateFormat DATE_FORMAT = new SimpleDateFormat( DATE_PATTERN ); // WRONG!

Using this member by 2 concurrent treads will lead to error.

What is a solution?
One solution is to create new SimpleDateFormat( DATE_PATTERN ) each time you need to parse a date. Another solution is to create a Thread-safe version of DateFormat.

That's it:


import java.lang.ref.SoftReference;
import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* Thread-safe version of java.text.DateFormat.
* You can declare it as a static final variable:
*
* private static final ThreadSafeDateFormat
* DATE_FORMAT = new ThreadSafeDateFormat( DATE_PATTERN );
*/
public class ThreadSafeDateFormat extends DateFormat
{
private static final long serialVersionUID = 3786090697869963812L;

private final String m_sDateFormat;

public ThreadSafeDateFormat(String sDateFormat)
{
m_sDateFormat = sDateFormat;
}

private final ThreadLocal m_formatCache = new ThreadLocal()
{
public Object get()
{
SoftReference softRef = (SoftReference) super.get();
if (softRef == null || softRef.get() == null)
{
softRef = new SoftReference(
new SimpleDateFormat(m_sDateFormat) );

super.set(softRef);
}
return softRef;
}
};

private DateFormat getDateFormat()
{
return (DateFormat) (
(SoftReference)m_formatCache.get()).get();
}

public StringBuffer format(Date date,
StringBuffer toAppendTo, FieldPosition fieldPosition)
{
return getDateFormat().format(
date, toAppendTo, fieldPosition);
}

public Date parse(String source, ParsePosition pos)
{
return getDateFormat().parse(source, pos);
}
}



The main idea of this class is storing separate instances of SimpleDateFormat for separate Threads in ThreadLocal variable. If 2 concurrent threads try to parse date, the will use 2 different instances of SimpleDateFormat.