Reference: https://mp.weixin.qq.com/s/snIrtOAjFWhOYHrfT9hDqA
Have a problem
A date utility class wrapped in a project was recently used in a multithreaded environment
A utility class for date conversion
This utility class is then used in a multithreaded environment
The results were abnormal
This exception is not analyzed from the source point of view, write a small Demo, understand this small Demo, understand the reason
A utility class that adds 10 to a number
And then part of the code output is
What the hell? You add 10, and you output 28? AddNum is set to 0, 3, and 7, but the thread does not complete the switch. When one thread sets the addNum value to 18, the thread starts to execute the addNum+10 step. They all output 28. SimpleDateFormat has a similar reason, so how do we solve this problem?
The solution
Solution 1: Every time you come to new, the space waste is relatively large
Solution 2: Methods modified with synchronized cannot be synchronized
Solution 3: Use the jdK1.8 DateFormatter, DateTimeFormatter class, but don’t want to change the code that uses the utility class in the project
Solution 4: Use ThreadLocal, one SimpleDateFormat object per thread
The above + 10 utility class can be changed to the following form (mainly to demonstrate ThreadLocal usage)
Both utility classes now work properly. Why?
The principle of analysis
When multiple threads read and write the same shared variable at the same time, there is no concurrency problem. If there is no sharing, there is no concurrency problem. One thread stores its own variable, which is similar to the original several people playing the same ball. The Thread class already has a Map container for variables. Its general structure is shown below
ThreadLocalMap is a Map, the key is ThreadLocal, and the value is Object
The mapping to the source code looks like this:
ThreadLocalMap is a static inner class of ThreadLocal
Put values into ThreadLocalMap
Value from ThreadLocalMap
Look back at the original example, is it clear?