How to use Simpledateformat in concurrent environments?

Asked

Viewed 805 times

15

The class SimpleDateFormat is not thread safe. I recently had problems with class instances SimpleDateFormat in static context being used by multiple threads concurrently in a web application.

private static final DateFormat df = new SimpleDateFormat("dd/MM/yyyy");

How should I proceed to ensure synchronization / competition with the minimum of overhead? For example, I should use syncronized, create an instance ThreadLocal or who knows how to create a new instance of the object SimpleDateFormat each call to the date formatting method (paying the price of constructing the object)?

4 answers

13


The price of building the object is usually very low. Unless you are creating several DateFormats in a loop (possibly under many layers of abstraction), and the creation time of the DateFormat is dominating the run time, so the best thing to do is to use the constructor.

Even if this is the case, it will usually be possible to refactor the code in order to place the DateFormat in a local variable or in a parameter (even more so than in the original code it was in a static variable). The operation is similar to encapsulating the use of a field and instead putting in getter. For example:

// Antes:
private static final DateFormat df = new SimpleDateFormat("dd/MM/yyyy");

private void metodoPrincipal() {
   ... blablabla ...
   metodoQualquer();
   ... blablabla ...
}

private void metodoQualquer() {
   ... blablabla ...
   x = df.metodoQualquer(parametros);
   ... blablabla ...
}

// Depois
private static final DateFormat createFormat() {
    return new SimpleDateFormat("dd/MM/yyyy");
}

private void metodoPrincipal() {
   ... blablabla ...
   metodoQualquer(createFormat());
   ... blablabla ...
}

private void metodoQualquer(DateFormat df) {
   ... blablabla ...
   x = df.metodoQualquer(parametros);
   ... blablabla ...
}

If it means you have to put parameters in dozens of places and with it break the signature of many methods, maybe the ThreadLocal be a better alternative.

If you plan to use Java 8 or higher, you can definitely use the class DateTimeFormatter. As quoted in the documentation (in English) it is immutable and thread-safe. Using this new class, your problem disappears.

8

I personally think it’s best to set aside all pre-Jjava 8 date and time classes and use the JODA Time. JODA Time in general is immutable and thread-safe. With it, would look like this:

// A diferença DateTimeFormatter/DateTimeFormat não é erro
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy");
DateTime date = formatter.parseDateTime("11/12/2013")
String text = formatter.print(date);

In Java 8 there is a new API, a result of JSR-310 (see also the github project), which was inspired by JODA Time. Despite this, this API is slightly different, and would look like this:

// qualquer das classes de data pode ser usada no lugar de LocalDate abaixo
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate date = LocalDate.parse("11/12/2013", formatter);
String text = date.toString(formatter);

If you are using Java 7, you also have the option of a JSR-310 backport. The basis of import is different (org.threeten.bp instead of java.time), but the rest of the code is essentially the same.

Like the parser/Formatter, the date and time classes, duration, interval and instant, both Java 8 and JODA Time, are immutable and thread safe.

  • 1

    While Victor’s answer is the most accurate for the question I asked, I believe that JODA Time is the best option in general. I’m sure this time JSR 310 co-led by our beloved Michael Nascimento Santos will be included in Java 8, but until then, nothing like JODA Time.

4

  • This is what I do when it is necessary to support multiple threads in this system.

3

Such a simple and almost insignificantly more "performative" to the creation on demand of instances of the SimpleDateFormat, as presented by Victor, is cloning.

A performance test is presented in this OS response, where cloning is almost 3 times more efficient.

Let’s look at an example of implementation:

static DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
static DateFormat createFormat() {
    return (DateFormat) df.clone();
}

On the other hand, on the same page cited above, the method that performed best was the creation of a pool of instances. In this concept, a number n of class instances SimpleDateFormat where n >= nº de threads, is the most efficient way.

However, my answer only aims to contribute some particularities on the subject. I agree that almost all applications developed do not need such "optimization" as there are numerous other bottlenecks that impact more on the overall performance of the application.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.