Test code:
public class Main {public static void Main (string[] args) {for (int k = 0; k < k++) { Runnable target = new Runnable () { @Override public void Run () { Object obj = Dateformatter.get (); System.out.println (Thread.CurrentThread (). GetName () + " = +" + obj); obj = Dateformatter.get (); } }; New Thread (target, K + ""). Start ();} } private static final threadlocal<simpledateformat> dateformatter = new Threadlocal<simpledateformat> () { c16/> @Override protected SimpleDateFormat initialvalue () { return new SimpleDateFormat ("Yyyy-mm-dd"); } };}
Output Result:
8 = [email protected]
5 = [email protected]
6 = [email protected]
...
7 = [email protected]
Hey? Why is it all f67a0200 an instance? Trace Threadlocal code to find out why, best not the solution. Finally suddenly suspected is simpledateformat in the ToString method of the problem, simpledateformat#tostring source code as follows:
Public String toString () { return getclass (). GetName () + "@" + integer.tohexstring (Hashcode ()); }
The Simpledateformat#hashcode code is as follows, where the pattern variable is the format string value of SimpleDateFormat (public SimpleDateFormat (string pattern)).
@Override public int hashcode () { return pattern.hashcode (); Just enough fields for a reasonable distribution }
So as above reasons can be learned, because of their own implementation of the InitialValue method of the SimpleDateFormat pattern are the same, so different SDF instances of the ToString final output is the same.
Protected SimpleDateFormat InitialValue () { return new SimpleDateFormat ("Yyyy-mm-dd"); }
Cause of Confusion:
Usually subclasses do not rewrite the ToString method, we can easily determine whether the ToString value is an instance, but because SimpleDateFormat itself implemented ToString so this rule is not in effect.
Remind:
In the future, as far as possible do not simply use the ToString output to determine whether it is an instance, if you need to judge this, be sure to check the ToString method.
Expand:
In the Java.lang.threadlocal#getmap method, it can be found that the Java thread has support for threading local variables, and there is a THREADLOCALMAP member variable in thread. Java.lang.threadlocal#getmap source code is as follows:
Threadlocalmap Getmap (Thread t) {
Threadlocals is a default modifier member variable return t.threadlocals; }
Threadlocal solve the confusion in SimpleDateFormat multithreading security problem