"JAVA" Jdk-simpledataformat thread is unsafe!

Source: Internet
Author: User

Label:

Problem

Publicclassprovenotsafe {Staticsimpledateformat df = Newsimpledateformat ("dd-mmm-yyyy", Locale.US);     Staticstring testdata[] = {"01-jan-1999", "14-feb-2001", "31-dec-2007"};        Publicstaticvoidmain (string[] args) {Runnable r[] = newrunnable[testdata.length];            for (inti = 0; i < r.length; i++) {finalinti2 = i; R[i] = newrunnable () {Publicvoidrun () {try{for (INTJ = 0; J &lt ; 1000;                            J + +) {String str = testdata[i2];                            String str2 = null;                                /* Synchronized (DF) */{Date d = df.parse (str);                                STR2 = Df.format (d); System.out.println ("I:" + I2 + "\TJ:" + j + "\tthreadid:" + thread.currentthread () . GetId () + "\tthreadname:" + thread.currentthread (). gEtname () + "\ T" + str + "\ T" + str2); } if (!str.equals (str2)) {thrownewruntimeexception ("date convers Ion failed after "+ j +" iterations.                            Expected "+ str +" but got "+ str2); }}} catch (ParseException e) {thrownewruntimeexception (                    "Parse failed");            }                }            };        Newthread (R[i]). Start (); }    }}

  

Test results i:  2 j:  0 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  1 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  2 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  3 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  4 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  5 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  6 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  7 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  8 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  9 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  10 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  11 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  12 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  13 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  14 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  15 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  16 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 31 -Dec- 2007 i:  2 j:  17 ThreadID:  10 ThreadName: Thread- 2 31 -Dec- 2007 11 -Jan- 1999 i:  0 j:  0 ThreadID:  8 ThreadName: Thread- 0 01 -Jan- 1999 11 -Jan- 1999 Exception in thread  "Thread-2" i:  1 j:  0 ThreadID:  9 ThreadName: Thread- 1 14 -Feb- 2001 11 -Jan- 2001 Exception in thread  "Thread-0" java.lang.RuntimeException: date conversion failed after  0 iterations. Expected  01 -Jan- 1999 but got  11 -Jan- 1999      at test.date.ProveNotSafe$ 1 .run(ProveNotSafe.java: 30 )      at java.lang.Thread.run(Thread.java: 619 ) Exception in thread  "Thread-1" java.lang.RuntimeException: date conversion failed after  0 iterations. Expected  14 -Feb- 2001 but got  11 -Jan- 2001      at test.date.ProveNotSafe$ 1 .run(ProveNotSafe.java: 30 )      at java.lang.Thread.run(Thread.java: 619 ) java.lang.RuntimeException: date conversion failed after  17 iterations. Expected  31 -Dec- 2007 but got  11 -Jan- 1999      at test.date.ProveNotSafe$ 1 .run(ProveNotSafe.java: 30 )      at java.lang.Thread.run(Thread.java: 619 )

 

[Cause of problem]

The SimpleDateFormat and DateFormat classes are not thread-safe. The reason we ignore thread safety is because the interfaces that SimpleDateFormat and DateFormat provide to us do not show how it is related to thread safety. Just at the bottom of the JDK documentation is the following description:

The date format in SimpleDateFormat is not synchronized. It is recommended (recommended) to create a separate format instance for each thread. If multiple threads access a format at the same time, it must remain externally synchronized.

The JDK original document is as follows:
Synchronization:
Date formats is not synchronized.
It is recommended to the create separate format instances for each thread.
If Multiple threads access a format concurrently, it must be synchronized externally.

Let's look at the JDK source code to see why the SimpleDateFormat and DateFormat classes are not the real reason for thread safety:

SimpleDateFormat inherits DateFormat, which defines the object of the Calendar class for a protected attribute in DateFormat: Calendar. Just because the calendar tired concept complex, involved in time zone and localization and so on, the JDK implementation of the use of member variables to pass parameters, which results in a multi-threaded error occurs.

There is a piece of code: The parent class: DateFormatprotected Calendar Calendar;Sub-Category: SimpleDateFormat
   Called from format after creating a fielddelegate    private stringbuffer Format (date date, StringBuffer toappendto,
   fielddelegate delegate) {        //Convert input date to Time field List        calendar.settime (date);        for (int i = 0; i < compiledpattern.length;) {            int tag = compiledpattern[i] >>> 8;     int count = compiledpattern[i++] & 0xff;     if (count = = 255) {  count = compiledpattern[i++] <<;  Count |= compiledpattern[i++];     }     Switch (TAG) {case     Tag_quote_ascii_char:  toappendto.append ((CHAR) count);  break;     Case Tag_quote_chars:  toappendto.append (Compiledpattern, I, count);  i + = count;  break;     Default:                Subformat (Tag, count, delegate, toappendto);  break;     } }        return toappendto;    }

  

Calendar.settime (date) This statement changes the calendar, and later, the calendar is used (in the Subformat method), which is the root cause of the problem. Imagine that in a multithreaded environment, two threads hold an instance of the same simpledateformat, calling the Format method, respectively:
Thread 1 calls the Format method, which changes the Calendar field.
The interruption came.
Thread 2 starts execution and it also changes the calendar.
was interrupted again.
Thread 1 comes back, and at this point, the calendar is not the value it set, but the path of thread 2 design. If more than one thread competes for the Calendar object at the same time, there are various problems, such as incorrect timing, thread hangs, and so on.
Analysis of the implementation of format, we are not difficult to find that the use of member variables calendar, the only advantage is that when the call Subformat, the lack of a parameter, but brought many of these problems. In fact, as long as here with a local variable, all the way down, all the problems will be solved.
There is a more important problem behind this question-stateless: one of the benefits of a stateless approach is that it can be safely invoked in a variety of environments. To measure whether a method is stateful, see if it changes something else, such as a global variable, such as an instance field. The Format method changes the Calendar field of the SimpleDateFormat during the run, so it is a stateful [workaround] 1. Create a new instance when needed:
SimpleDateFormat SDF = new SimpleDateFormat ("Yyyy-mm-dd HH:mm:ss");
2. Synchronous code block synchronized
privatestatic SimpleDateFormat sdf = new SimpleDateFormat ("Yyyy-mm-dd HH:mm:ss");          Publicstatic String formatdate (date date) throws parseexception{        synchronized (SDF) {            return Sdf.format (date);        }      }        Publicstatic Date Parse (String strdate) throws parseexception{        synchronized (SDF) {            return sdf.parse (strdate);        }    
3. Use ThreadLocal:It is also the sharing of variables to be exclusive, thread-exclusive can be compared to the method alone in the concurrency environment can reduce the cost of many objects created. This approach is generally recommended if performance requirements are high.

"JAVA" Jdk-simpledataformat thread is unsafe!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

Tags Index: