Creating DateFormat Threadsafe. What to use, synchronize

I want to make the following stream of code safe. What is the best way to achieve it?

private static final DateFormat DATE_FORMAT = DateFormat.getDateTimeInstance(); public static final String eventTypeToDateTimeString(long timestamp) { return DATE_FORMAT.format(new Date(timestamp)); } 
+8
java multithreading thread-safety
source share
6 answers

Avoid obsolete time classes

The java.time classes have been replaced by the difficult old time classes associated with the earliest versions of Java. The java.time classes are thread safe and use immutable objects .

java.time

Replace formatting types and dates with java.time types to automatically ensure thread safety.

If you want, define your DateTimeFormatter globally. This class can automatically localize the generated string or specify a specific format.

  • Specify FormatStyle to determine the length of the abbreviation.
  • Indicate Locale to define (a) human language for translating the name of the day, the name of the month, etc. And (b) cultural norms that address issues of contraction, capitalization, punctuation, etc.
  • Specify the ZoneId for the time zone where you can configure the moment.

The Instant class represents a moment in the UTC timeline with a nanosecond resolution. The ZonedDateTime class sets Instant to a specific time zone.

Your code translated into java.time classes. In real work, I would break it into several lines and catch for exceptions.

 private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ; private static final ZoneId ZONE_ID = ZoneId.of( "America/Montreal" ); public static final String eventTypeToDateTimeString(long timestamp) { return Instant.ofEpochMilli( timestamp ).atZone( ZONE_ID ).format( DATE_TIME_FORMATTER ); } 

Do not track date-time as a countdown from an era

I do not recommend laying a long path for representing date and time values. It makes debugging and registration difficult, since a person cannot distinguish between the meaning of date and time. Instead, switch to java.time types such as Instant . Using java.time types ensures type safety and makes your code more self-documenting.


About java.time

The java.time framework is built into Java 8 and later. These classes supersede the nasty old obsolete time classes such as java.util.Date , Calendar and SimpleDateFormat .

The Joda-Time project, now in maintenance mode , advises switching to the java.time classes.

To learn more, check out the Oracle tutorial . And search for qaru for many examples and explanations. The specification is JSR 310 .

You can exchange java.time objects directly with your database. Use a JDBC driver compatible with JDBC 4.2 or later. No strings needed, no java.sql.* Needed.

Where can I get java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proof of possible future additions to java.time. Here you can find useful classes such as Interval , YearWeek , YearQuarter and others .

+9
source share

There are several alternatives with various tradeoffs.

You can synchronize access to a single DateFormat date. This minimizes the number of formatting objects created, but other threads will have to fight for blocking before they can access formatting. This is probably the worst performance alternative; many threads may end up wasting time, and the more threads you have, the worse.

You can create a new DateFormat object for each use. This will eliminate the contradictions between the streams, but if there are many date formats, you can put pressure on the garbage collector using this approach, and this will hurt the work. But in many cases, this can work quite well and very simply.

The third option, which makes the DateFormat of the threadlocal variable, is much more efficient. There is no competition between streams, and formatting can be reused by a stream multiple times, so it does not create almost as much garbage. The disadvantages will be that this is the least straightforward approach, and any objects that you put in threadLocal may stick for longer than you want if you don't clear them.

+4
source share

Just create a new copy for each call until it demonstrates that it is a performance issue. The overhead associated with manually managing streaming locales is likely to soak up any advantage that you get from caching them.

+3
source share

You can

  • Create a new instance of DateFormat every time you need it.

  • Use the synchronized block as pointed out by @Giovanni Botta.

  • Use ThreadLocal :

     private static final ThreadLocal<DateFormat> THREADLOCAL_FORMAT = new ThreadLocal<DateFormat>() { @Override protected DateFormat initialValue() { return DateFormat.getDateTimeInstance(); } }; public static final String eventTypeToDateTimeString(long timestamp) { return THREADLOCAL_FORMAT.get().format(new Date(timestamp)); } 

Actually, using ThreadLocal can give you better performance if you have a thread pool (which means threads are reused), which is what most web containers do.

Link

http://www.javacodegeeks.com/2010/07/java-best-practices-dateformat-in.html

+2
source share

Better use: org.apache.commons.lang.time.FastDateFormat (this is a quick and thread safe version of SimpleDateFormat)

+2
source share

The simplest solution:

 synchronized public static final String eventTypeToDateTimeString(long timestamp) { return DATE_FORMAT.format(new Date(timestamp)); } 

You do not need to use ThreadLocal , as this is all in a static context.

0
source share

All Articles