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?