How to use SimpleDateFormat in competing environments?

15

The class SimpleDateFormat is not thread safe . I recently had problems with instances of class 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 do I 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 SimpleDateFormat object with each call to the date formatting method (paying the price of the object's construction)?

    
asked by anonymous 11.12.2013 / 20:55

4 answers

12

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

Even if this is the case, it will usually be possible to refactor the code to put DateFormat into a local variable or a parameter (even more than in the original code it was in a static variable). The operation is similar to that of encapsulating the use of a field and instead putting it into 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 this means you have to put parameters in dozens of places and break the signature of many methods, maybe ThreadLocal is a better alternative.

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

    
11.12.2013 / 21:08
8

I personally think it's best to set aside all pre-Java 8 date and time classes and use JODA Time >. JODA Time is generally immutable and thread-safe. With it, 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

12.12.2013 / 03:20
4

According to link , using ThreadLocal is the which gives higher performance. Analyze the context and see if instantiating the objects does not have a very high cost.

    
11.12.2013 / 21:08
2

A simple and nearly insignificant alternative to the on-demand creation of instances of SimpleDateFormat , as presented by Victor, is cloning.

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

Let's look at an example implementation:

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

On the other hand, on the same page mentioned above, the method that performed best was creating an pool of instances. In this concept, a% number of instances of class n where SimpleDateFormat , is the most efficient way.

However, my answer is only to contribute with some particularities on the subject. I agree that almost all of the applications developed do not need such "optimization" because there are a number of other bottlenecks that impact the overall performance of the application.

    
13.01.2014 / 14:30