[ACCEPTED]-Synchronizing access to SimpleDateFormat-simpledateformat
Creating SimpleDateFormat is expensive. Don't use 11 this unless it's done seldom.
OK if you can 10 live with a bit of blocking. Use if formatDate() is 9 not used much.
Fastest option IF you reuse 8 threads (thread pool). Uses more memory than 2. and 7 has higher startup overhead.
For applications 6 both 2. and 3. are viable options. Which 5 is best for your case depends on your use 4 case. Beware of premature optimization. Only 3 do it if you believe this is an issue.
For 2 libraries that would be used by 3rd party 1 I'd use option 3.
The other option is Commons Lang FastDateFormat but you 6 can only use it for date formatting and 5 not parsing.
Unlike Joda, it can function 4 as a drop-in replacement for formatting. (Update: Since 3 v3.3.2, FastDateFormat can produce a FastDateParser, which 2 is a drop-in thread-safe replacement for 1 SimpleDateFormat)
If you are using Java 8, you may want to 1 use java.time.format.DateTimeFormatter
:
This class is immutable and thread-safe.
e.g.:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String str = new java.util.Date().toInstant()
.atZone(ZoneId.systemDefault())
.format(formatter);
Commons Lang 3.x now has FastDateParser 4 as well as FastDateFormat. It is thread 3 safe and faster than SimpleDateFormat. It 2 also uses the same format/parse pattern 1 specifications as SimpleDateFormat.
Don't use SimpleDateFormat, use joda-time's 5 DateTimeFormatter instead. It is a bit stricter 4 in the parsing side and so isn't quite a 3 drop in replacement for SimpleDateFormat, but 2 joda-time is much more concurrent friendly 1 in terms of safety and performance.
I would say, create a simple wrapper-class 9 for SimpleDateFormat that synchronizes access 8 to parse() and format() and can be used 7 as a drop-in replacement. More foolproof 6 than your option #2, less cumbersome than 5 your option #3.
Seems like making SimpleDateFormat 4 unsynchronized was a poor design decision 3 on the part of the Java API designers; I 2 doubt anyone expects format() and parse() to 1 need to be synchronized.
Another option is to keep instances in a 12 thread-safe queue:
import java.util.concurrent.ArrayBlockingQueue;
private static final int DATE_FORMAT_QUEUE_LEN = 4;
private static final String DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";
private ArrayBlockingQueue<SimpleDateFormat> dateFormatQueue = new ArrayBlockingQueue<SimpleDateFormat>(DATE_FORMAT_QUEUE_LEN);
// thread-safe date time formatting
public String format(Date date) {
SimpleDateFormat fmt = dateFormatQueue.poll();
if (fmt == null) {
fmt = new SimpleDateFormat(DATE_PATTERN);
}
String text = fmt.format(date);
dateFormatQueue.offer(fmt);
return text;
}
public Date parse(String text) throws ParseException {
SimpleDateFormat fmt = dateFormatQueue.poll();
if (fmt == null) {
fmt = new SimpleDateFormat(DATE_PATTERN);
}
Date date = null;
try {
date = fmt.parse(text);
} finally {
dateFormatQueue.offer(fmt);
}
return date;
}
The size of dateFormatQueue 11 should be something close to the estimated 10 number of threads which can routinely call 9 this function at the same time. In the worst 8 case where more threads than this number 7 do actually use all the instances concurrently, some 6 SimpleDateFormat instances will be created 5 which cannot be returned to dateFormatQueue 4 because it is full. This will not generate 3 an error, it will just incur the penalty 2 of creating some SimpleDateFormat which 1 are used only once.
I just implemented this with Option 3, but 4 made a few code changes:
- ThreadLocal should usually be static
- Seems cleaner to override initialValue() rather than test if (get() == null)
You may want to 3 set locale and time zone unless you really 2 want the default settings (defaults are 1 very error prone with Java)
private static final ThreadLocal<SimpleDateFormat> tl = new ThreadLocal<SimpleDateFormat>() { @Override protected SimpleDateFormat initialValue() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-hh", Locale.US); sdf.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); return sdf; } }; public String formatDate(Date d) { return tl.get().format(d); }
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.