Although threadlocal is associated with concurrency problems, many program apes only use it as a tool for "easy access", and Fat Man feels that this may not be the purpose of threadlocal design, which itself is designed for thread safety and some specific scenarios.
What is threadlocal?
Each threadlocal can put a thread-level variable, but it can be shared by multiple threads, and can be thread-safe for the sake of absolute thread safety.
Like what:
Public final static threadlocal<string> RESOURCE = new threadlocal<string> ();
resource represents a Threadlocal object that can hold a string type. At this point, no matter what one thread can access this variable concurrently, write to it, read operations, are thread-safe. For example, a thread passes the Resource.set ("AAAA") and writes the data to Threadlocal, where it is able to pass the Resource.get () or the value.
but it is not perfect, there are many flaws, just as we rely on it to do the same as the number of passes. And then we'll analyze some of its bad places.
Why do you sometimes use threadlocal as a convenient way to pass a number of parameters? For example, when many methods call each other, the original design may not think too much, the number of arguments to pass how many variables, then the whole process of the pass is fragmented. Further thinking: If the A method calls the B method, the 8 parameters are passed. The B method next calls the C method->d method->e method->f method and so on only need 5 parameters, at this time when the API is designed to involve 5 parameters of the entrance. These methods are reused in many places during the course of business development.
One day. We find that the F method has to add a parameter, which is in the entry parameters of the A method, at which point it is assumed that the middle method involves a large number of facets. And do not know if there will be a bug after the change.
As a program ape we may be with the thought, threadlocal anyway is the overall, put here. Really good solution.
But at this point you will find that the system is a bit like a patch in this way. The more we paste, the more we need to ask the relevant code to use Threadlocal to pass this parameter, which may be messy. In other words, it is not to be used. But we have to understand that its entrances and exits are controllable.
The weirdest thing about threadlocal is the "scope", especially when the code is very messy at the beginning of the design, assuming you add a lot of threadlocal. The system will gradually become a stays situation. With such a convenient thing. Many small partners may be less concerned about design, as we all feel that these problems can be solved by means of change. Fat brother thinks this is a vicious circle.
For this kind of business scenario. should be prepared in advance. Requires a coarse-grained business model. Even if you want to use threadlocal, do not add a parameter to add a threadlocal variable. For example, we are able to design several objects to encapsulate the entry parameters, which are based on the object at the interface design time.
Perhaps a class cannot express all of the reference meanings, and so easy leads to strong coupling.
Usually we break down the business model into several large types of objects as their parameter wrapper, and will be in accordance with the object property sharing, abstract, at each level of the inheritance relationship to expand the corresponding parameters, or the addition of the number of objects in the object, the shared parameters are defined in the parent class, this parameter is gradually normalized.
Let's go back to the point and discuss what threadlocal is for? For this we explore several topics below.
(1) Application scenarios and how to use themto illustrate the application scenario for threadlocal. Let's look at a sample of a framework. Spring's transaction manager uses AOP to cut into business code and, before entering the business code, extracts the corresponding transaction object according to the corresponding transaction manager, if the transaction manager is Datasourcetransactionmanager, A connection object is obtained from the DataSource, which is saved in threadlocal by a certain wrapper. And spring also wraps the DataSource, rewriting the Getconnection () method, or the return of the method is controlled by spring, so that spring enables the same connection object to be fetched multiple times within the thread.
Why do you put it in threadlocal? Since spring does not pass the parameters to the application after AOP. Each business code for an application is defined in advance, and spring does not require that connection's entry parameters be written in the entry parameters of the business code. Spring chooses threadlocal, which guarantees that the connection object is always inside the thread, and whenever it is available, spring is clear when the connection is recycled, It is clear when this element is removed from the threadlocal (described in section 9.2).
Can be seen from the design of the spring transaction manager. Spring uses threadlocal to get a very perfect design idea, and at the same time it is very clear at design time when threadlocal elements should be deleted. As a result, we simply feel that threadlocal is best used in a global design. Rather than an indirect method of patching.
Once you've seen the basic scenarios, here's a sample. Defines a class for holding static Threadlocal objects, which are set, get operations on threadlocal objects in parallel with multiple threads, and the values are printed. Take a look at the values that each thread sets in itself and whether the values are the same.
The code is as follows:
Code Listing 5-8 Simple threadlocal Example
/span>
public class Threadlocaltest {static class Resourceclass {public final static threadlocal<string> resource_1 = New Threadlocal<string> ();p ublic final static threadlocal<string> resource_2 = new threadlocal< String> ();} Static class A {public void Setone (String value) {ResourceClass.RESOURCE_1.set (value);} public void Settwo (String value) {ResourceClass.RESOURCE_2.set (value);}} Static class B {public void display () {System.out.println (ResourceClass.RESOURCE_1.get () + ":" + Resourceclass.resource_ 2.get ());}} public static void Main (String []args) {Final A = new A (), final b b = new B (), for (int i = 0; i < +; I + +) {final S Tring Resouce1 = "thread-" + i;final String resouce2 = "VALUE = (" + I + ")"; new Thread () {public void run () {try {A.setone (r Esouce1); A.settwo (RESOUCE2); B.display ();} finally {ResourceClass.RESOURCE_1.remove (); ResourceClass.RESOURCE_2.remove ();}}}. Start ();}}}
For this code, let's start with a few words.
Two threadlocal variables are defined. Finally the goal is to see whether the last two values can be correspondingly. This gives the opportunity to prove that the data that threadlocal holds may be thread-private.
The use of two internal classes is just to make the test simple, easy to understand, we can also be the sample code to split into multiple classes, the result is the same.
The test code is more like a convenient way to pass a number of parameters. Because it's really handy to pass the parameters, it's just for testing.
In finally there is a remove () operation, which is used to clear the data.
Why do you want to erase the data and continue with the details later in this article?
test results such as the following:
Thread -6:value = (6)
Thread -9:value = (9)
thread -0:value = (0)
thread -10:value = (Ten)
Thread -12:value = (a)
Thread -14:value = (+)
Thread -11:value = (one)
Thread -3:value = (3)
Thread -5:value = (5)
Thread -13:value = (in)
Thread -2:value = (2)
Thread -4:value = (4)
Thread -8:value = (8)
Thread -7:value = (7)
Thread -1:value = (1)
you can see the thread order of the output is not the order of the initial definition of the thread, in theory can be explained that multithreading should be run concurrently, but still be able to maintain the value of each thread is corresponding, indicating that these values have reached the purpose of the thread private.
not that shared variables are not thread-private? How does it do thread-private? This requires that we know a little bit about the principle of things. Otherwise it is not so reassuring to use, please see the following introduction.
(2) threadlocal intrinsic principleFrom the previous operation, it can be found that the most common operation of threadlocal is set, get, remove three actions. Take a look at what these three actions actually did. First look at the set operation, as seen in source code fragment 5-5.
Figure 5-5 Threadlcoal.set Source code fragment
The first code in Figure 5-5 takes out the current thread T. The Getmap (t) method is then called when the current thread is passed in, in other words. The Threadlocalmap returned by this method has something to do with the current thread, which we'll record first.
Further determine that the map is not empty. Then the key set to the map is this. The value is the externally passed-in argument. What is this? is the defined Threadlocal object.
There are two paths in the code that need to be traced, each of which is getmap (thread) and Createmap (thread, T). First look at the Getmap (T) operation. 5-6 of what you see.
Figure 5-6 Getmap (Thread) operation
Over here. We see that Threadlocalmap is actually a property within a thread that is defined in the thread class as:
Threadlocal.threadlocalmap threadlocals = null;
Such a method is very easy to confuse, because this threadlocalmap is the inner class inside the threadlocal. Placed inside the thread class as a property exists. The threadlocal itself becomes the key stored in the map, and the value entered by the user is values.
It's too messy. It's not clear, draw a picture to see (see Figure 5-7).
Simply put, this map object exists as a private variable inside thread, so it is thread-safe. Threadlocal gets the current thread by Thread.CurrentThread () to get the map object. At the same time, it initiates writes and reads itself as a key, because it takes itself as a key, so that a Threadlocal object can hold the corresponding Java object in one thread. This object can also be found naturally through get.
When the variable string A is defined, the "a" is actually just a name (in the 3rd chapter, Chang), the virtual machine needs to find the corresponding information through the symbol table, which is just like a k-v structure, the underlying processing is very close to this. The process here is to explicitly use the map to hold the data, which is also a way to implement the workaround.
Now there's a train of thought. Continue to go back to the above topic, in order to verify the previous judgment and understanding, look at the details of the Createmap method, 5-8 see.
figure 5-8 Createmap operation
Span style= "font-size:14px" > This code is to run an operation to create a new map. And the first value as the initialization value of this map, because this map is thread-private. It's impossible to have a thread also doing a put operation on it at the same time, so the assignment and initialization here are absolutely thread-safe, and at the same time ensure that each externally written value is written to the map object.
It gives us the feeling that this implementation is a skill, not a technique.
In fact, skill or technology is totally from a certain point of view. Or at some level of abstraction, assuming this code is implemented in C + +, is it called technology, not skill? Of course not. Fat brother feels that technology is still based on ideas and methods, just to see what level of abstraction is achieved. Like some of the basic principles explored in this book, we explored its thinking, in fact it is based on some kind of skill and means, just to package the program into some kind of grammar and API, so fat Brother think, once learned to use skills to think about the problem, learned to look at technology by skill itself. We should learn a kind of flexible and divergent thinking through this kind of design. Learn to understand all kinds of scenes. This can accumulate a lot of real wealth, which is not available through the use or testing of certain tools.
Is this design of threadlocal perfect?
Not very perfect, it still has a lot of pits, here to its easy misleading program ape as a reference tool is no longer mentioned. Let's look at some of the technical problems that are caused by improper use of it.
(3) Threadlocal's pitThrough the above analysis. We can realize that threadlocal is actually a variable that is bound to a thread, so there is a problem: assuming that the variable within the threadlocal is not removed or replaced, its life cycle will coexist with the thread.
Therefore, a very large "pit" of threadlocal is when used improperly, causing the user to not know its scope.
You might think that threadlocal should be recycled after the thread ends. It is true that the threads of the line is written off, but it is possible that this is not the case. Threading management in a thread pool, for example, is a thread-multiplexing approach (web containers are often used as thread pools). Thread pool threads are very difficult to end and even never end. This will mean that the duration of the thread will not be pre-measured or even consistent with the life cycle of the JVM.
Then the life cycle of the corresponding threadlocal variable will not be predicted.
Perhaps it doesn't matter if you define a few threadlocal variables in the system. Since each set of data is using the threadlocal itself as key, the same key will certainly replace the original data. The original data can be released, theoretically not causing any problems. But the world is not absolute, assuming threadlocal directly or indirectly wrapped in the collection class or complex objects, each time in the same threadlocal to take out the object, then the content to do the operation, then the internal collection class and complex objects occupy space may start to expand.
throw away the problem with the code itself. To give an extreme example. Assuming that you don't want to define too many threadlocal variables, you can use a hashmap to store them, which seems like no problem. Since threadlocal can be used anywhere in the program, it is difficult to know the source of this hashmap writing in some poorly designed code, in order to be safe in the code. It is common to check if the HashMap is present, and if it does not, create a hashmap to write it in. If it exists, it is usually not replaced. Because the code writer is generally "afraid" because of this substitution will throw away some from "other places write HashMap data". Which leads to many unforeseen problems.
in this case. HashMap first put into the threadlocal may not be released, and this hashmap may start to store a lot of key-value information, assuming that the value of the key stored in the business is constantly changing (for example, the business ID as key), Then the hashmap begins to grow longer and is likely to have one of these hashmap in every thread, gradually forming an indirect memory leak. There have been a lot of people who have eaten this loss and found that this code may not be in their own business system. But out of some two-party package, three-party package (open source does not guarantee that there is no problem).
to deal with such a problem is very complex, but first of all to ensure that the code you write is not a problem. Make sure no problem is not that we don't use threadlocal. Not even to learn it. Because it certainly has its application value. In the use of clear threadlocal is the most elusive is "do not know where the source" (generally the code is not designed to cause), only know the source of the end of the ability to control the part. Or we are from the design point of view to let the threadlocal set, remove the beginning and end, usually in the external call of the code using finally to remove the data, only to our careful thinking and abstraction can achieve this purpose. Some are two-party package, three-party package problem, for these problems we need to learn is to find the root cause of the problem to solve, about the two-party package, three-party package execution tracking, you can refer to section 3.7.9 describes the Btrace tool.
Add: In no matter what asynchronous program (including asynchronous I/O, non-clogging I/O), Threadlocal's parameter pass is unreliable, since the thread sends the request. It is no longer waiting for the remote return result to continue to run down, and after the actual return result, the processed thread may have another one.
#################################### #个人总结 ####################################
Thread.java in Source code:
Threadlocal.threadlocalmap threadlocals = null;
that is: Each thread object has a THREADLOCAL.THREADLOCALMAP member variable,ThreadLocal. Threadlocalmap is a static inner class of a threadlocal class (as seen below), so the thread class is able to reference it.
Static Class Threadlocalmap {
so each thread will have a reference to the Threadlocal.threadlocalmap object
When setting a value in Threadlocal:
public void Set (T value) { Thread T = Thread.CurrentThread (); Threadlocalmap map = getmap (t); if (map! = null) Map.set (this, value); else createmap (t, value); }
Threadlocalmap Getmap (Thread t) { return t.threadlocals; }
first gets a reference to the current thread, and then gets the Threadlocal.threadlocalmap object of the current thread (the t.threadlocals variable is the THREADLOCAL.THREADLOCALMAP variable). If the object is empty, create one, such as the following:
void Createmap (Thread T, T firstvalue) { t.threadlocals = new Threadlocalmap (this, firstvalue); }
the This variable is a reference to threadlocal, which is the same for every thread of the same threadlocal object , Each thread, however, has a Threadlocal.threadlocalmap object that holds the values of their respective threadlocal references as key, so they do not affect each other, and: Suppose you create a new Threadlocal object, This object is still stored in the same Threadlocal.threadlocalmap object as each thread, because a thread has only one Threadlocal.threadlocalmap object, This object is created when the first threadlocal is set for the first time, as described in the Createmap method.
Threadlocalmap (ThreadLocal Firstkey, Object firstvalue) { table = new Entry[initial_capacity]; int i = Firstkey.threadlocalhashcode & (initial_capacity-1); Table[i] = new Entry (Firstkey, firstvalue); size = 1; Setthreshold (initial_capacity); }
Summarize:
In-depth study of java.lang.ThreadLocal class: http://blog.csdn.net/xiaohulunb/article/details/19603611
API Description:
ThreadLocal (), t get (), protected T InitialValue (), void Remove (), void set (t value)
Typical examples:
1.Hiberante Session Tool Class Hibernateutil
2. Set bean properties through different thread objects to ensure the independence of individual thread bean objects.
Threadlocal General steps to use:
1, in multi-threaded classes (such as the Threaddemo Class). Create a Threadlocal object, threadxxx, to hold the object XXX between threads that need to be quarantined. 2, in the Threaddemo class. Create a method that gets the data to be quarantined getxxx (), inferred in the method that if the Threadlocal object is null, a new () object should be created to isolate the access type and cast to the type to be applied. 3, in the Threaddemo class of the Run () method. Gets the data to manipulate by using the GetXXX () method. This ensures that each thread corresponds to a data object that is manipulated at all times.
In contrast to synchonized:
Both threadlocal and synchonized are used to solve multi-threaded concurrent access questions. But the threadlocal and the synchronized have the essential difference. Synchronized is the mechanism by which a lock is used so that a variable or block of code can be interviewed by only one thread at a time. Instead, Threadlocal provides a copy of the variable for each thread, so that each thread is not interviewing the same object at a certain time, thus isolating data sharing from multiple threads. Synchronized, in contrast, is used to gain data sharing when communicating between multiple threads. Synchronized is used for data sharing between threads, while threadlocal is used for data isolation between threads.
A word to understand threadlocal: to threadlocal inside the store is to the map inside it to store things, and then threadlocal this map to hang under the current thread, so that map is only the thread.
Using threadlocal to improve the partitioning of your hierarchy (implementation of spring transactions): http://blog.csdn.net/zhouyong0/article/details/7761835
threadlocal:http://wangxinchun.iteye.com/blog/1884228 of source Code analysis
Threadlocal source code parsing in Java (top): http://maosidiaoxian.iteye.com/blog/1939142
Threadlocal and synchronized:http://blog.csdn.net/yangairong1984/article/details/2294572
Java threading: In-depth threadlocal:http://lavasoft.blog.51cto.com/62575/258459 (a threadlocal simulation implementation)
Java Multithreading (vi), Threadlocal class: http://blog.csdn.net/lonelyroamer/article/details/7998137
Java ThreadLocal (application scenario and how and how it works)