Java Programming Advanced Skills — ThreadLocal
For the java web applications or some multi-threading applications, you may need to maintain some context related to the current request/thread. If you want this context can be accessed in every classes, one way is you pass it as a parameter through every method call, another way is you make this context as static variables which is not thread-safe. Sounds those two ways are not smart ideals, so here comes the ThreadLocal.
You can find the demo project from here.
In our demo project we create a Zoo which may contains several Areas and each Area may contains several Buildings. Kinds of animals may live in a building. Then, for each customer we use a thread to trace where he or she have visited. In this demo project, the custom ID is the context shared by several classes.
The first implementation ( xxx_parameter functions ) we pass the context as a parameter through every method call, it increases the coupling between classes and you need to declare this parameter in each functions. However, the context can be shared correctly.
//testVisit_parameter() result snapshot
Customer 0 go into the zoo
Customer 3 go into the zoo
Customer 3 go into the area
Customer 3 go into the building
Panda says hi to customer 3
Customer 0 go into the area
Customer 0 go into the building
Panda says hi to customer 0
Customer 1 go into the zoo
Customer 2 go into the zoo
Customer 4 go into the zoo
Customer 4 go into the area
Customer 4 go into the building
Panda says hi to customer 4
Customer 2 go into the area
Customer 2 go into the building
Panda says hi to customer 2
Customer 1 go into the area
Customer 1 go into the building
Panda says hi to customer 1
The second implementation (xxx_threadLocal functions)we used ThreadLocal to achieve that.
private static ThreadLocal<String> id_threadLocal = new ThreadLocal<String>();public static String getId_threadLocal() {return id_threadLocal.get();}
As you can see, we can read the context by the static get function and we don’t need to handle the parameter anymore. The result also shows the context correctly.
//testVisit_threadLocal() result snapshot
Customer 0 go into the zoo
Customer 3 go into the zoo
Customer 3 go into the area
Customer 3 go into the building
Panda says hi to customer 3
Customer 1 go into the zoo
Customer 1 go into the area
Customer 1 go into the building
Panda says hi to customer 1
Customer 4 go into the zoo
Customer 4 go into the area
Customer 4 go into the building
Panda says hi to customer 4
Customer 2 go into the zoo
Customer 2 go into the area
Customer 2 go into the building
Panda says hi to customer 2
Customer 0 go into the area
Customer 0 go into the building
Panda says hi to customer 0
If someone forget to consider the point of thread-safe, he may try to implement it by static variable (xxx_static functions). As you can see, it will only be the latest value in all threads.
//testVisit_static() result snapshot
Customer 4 go into the zoo
Customer 4 go into the zoo
Customer 4 go into the area
Customer 4 go into the area
Customer 4 go into the building
Customer 4 go into the zoo
Panda says hi to customer 4
Customer 4 go into the building
Panda says hi to customer 4
Customer 4 go into the zoo
Customer 4 go into the area
Customer 4 go into the building
Customer 4 go into the zoo
Customer 4 go into the area
Customer 4 go into the area
Customer 4 go into the building
Panda says hi to customer 4
Panda says hi to customer 4
Customer 4 go into the building
Panda says hi to customer 4
Actually, for logging purpose we already have Mapped Diagnostic Context (MDC) to use, which also implement by ThreadLocal. However, if you have other thread context want to share across the classes, hope this article can give you some help!