Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a good thread safe Format caching library?

I want to do some formatting in my webapp, using MessageFormat, DateFormat, DecimalFormat, etc.

Since these are not thread-safe, one static instance for each usage won't work, but it seems wasteful to create a new XXXXFormat object each time one is needed. Caching and re-using them with a ThreadLocal seems like an obvious optimization.

This seems like a very common pattern, so I'm wondering if there are any appropriate libraries.

Instead of calling:

    DecimalFormat formatter = new DecimalFormat("###,##0.00");

    String formatted = formatter.format(value);             

every time I need to format something, why not:

    String formatted = FormatCache.formatDecimal("###,##0.00",numberValue);

where FormatCache would do the ThreadLocal caching with a HashMap keyed on the format pattern?

Presumably there'd be other methods like:

    String FormatCache.formatDecimal(String, Number);
    String FormatCache.formatDate(String, Date);
    String FormatCache.formatMessage(String, Object...);
like image 532
Brad Tofel Avatar asked Dec 15 '22 21:12

Brad Tofel


1 Answers

tl;dr

Cache a thread-safe DateTimeFormatter object (immutable).

Never use SimpleDateFormat. Use only java.time package for date-time work.

java.time

The troublesome old date-time classes such as DateFormat & SimpleDateFormat are now supplanted by the modern java.time classes. Specifically here, the DateTimeFormatter class.

Immutable objects, thread-safe

The java.time classes were designed to be Immutable Objects. This means that rather than modifying any content in the object, a new distinct object is generated. The original is left intact.

This, and other techniques, make the java.time classes thread-safe by design and are so documented.

DateTimeFormatter

DateTimeFormatter dateTimeFormatterFullQuébec = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ;

You can cache that object dateTimeFormatterFullQuébec, keep it around.

ZoneId

Likewise, you could keep a ZoneId time zone object cached.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId zoneMontréal = ZoneId.of( "America/Montreal" ) ;

Then use them any time, even across threads.

ZonedDateTime zdt = ZonedDateTime.now( zoneMontréal ) ;
String output = zdt.format( dateTimeFormatterFullQuébec ) ;

dimanche 4 mars 2018 à 18:36:32 Eastern Standard Time

The java.time objects such as ZonedDateTime and Instant are also immutable and thread-safe, just like the ZoneId & DateTimeFormatter. You can cache all of these, and use them across threads.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

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

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, and later
    • Built-in.
    • Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

like image 80
Basil Bourque Avatar answered Dec 26 '22 18:12

Basil Bourque