Deep learning to understand java-threadlocal

Source: Internet
Author: User
Tags locale

Guide
First, ThreadLocal is not used to solve multi-threaded access problems with shared objects, and in general, objects in the thread through Threadlocal.set () are objects that the thread itself uses, and other threads do not need access or access. Different objects are accessed in each thread.

In addition, it is said that threadlocal allows each thread to maintain its own independent object, not by Threadlocal.set (), but by creating an object through the operation of the new object in each thread, creating a copy or copy of each thread that is not an object. The reference to this newly created object is saved to a map of each thread by Threadlocal.set (), each thread has a map that executes Threadlocal.get (), and each thread pulls the object from its own map and So the objects in their own thread are taken out, and the threadlocal instance is used as the key to the map.

If Threadlocal.set () goes in the same object that multiple threads share, then the Threadlocal.get () of multiple threads gets the shared object itself, or there is a concurrent access problem.

What is threadlocal? What's the use? How to use it?
1. What is threadlocal?
With this problem, let's take a look at the important role molecule threadlocal in Java concurrency programming.
As early as the version of JDK 1.2, Java.lang.threadlocal,threadlocal provides a new way to solve the concurrency problem of multi-threaded threads. Using this tool class, you can write beautiful multithreaded programs very concisely.

When you use threadlocal to maintain variables, Threadlocal provides a separate copy of the variable for each thread that uses the variable, so each thread can independently change its own copy without affecting the copy of the other thread.

From the thread's point of view, the target variable is like a thread's local variable, which is the meaning of the "local" in the class name.

Therefore, the code to write thread-local variables in Java is relatively clumsy, resulting in thread-local variables not being well-popularized in Java developers.

interface method for Threadlocal

Threadlocal class interface is very simple, there are only 4 methods, let us first look at:

void set(Object value)设置当前线程的线程局部变量的值。public Object get()该方法返回当前线程所对应的线程局部变量。public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。

It is worth mentioning that, in JDK5.0, Threadlocal already supports generics, and the class name of the class has become threadlocal. The API methods are also adjusted accordingly, and the new version of the API method is void set (t value), t get (), and T InitialValue ().

How does threadlocal maintain a copy of a variable for each thread? The idea is simple: there is a map in the Threadlocal class that stores a copy of the variable for each thread, the key for the element in the map is the thread object, and the value corresponds to the variable copy of the thread.
What's the use?
Threadlocal If you simply look at the name as a "local thread" that means that the name is really not very good, it is easy to misunderstand, threadlocalvariable (thread local variable) should be a better name. Let's take a look at the official description of threadlocal.
This class provides thread-local (thread-local) variables. These variables are different from their ordinary counterparts, because each thread that accesses a variable (through its Get or set method) has its own local variable, independent of the initialized copy of the variable. ThreadLocal instances are typically private static fields in a class that want to associate the state with a thread (for example, a user ID or transaction ID).
1 . Each thread has its own local variable

Each thread has a context that is separate from the other threads to hold the variable, and the local variables of one thread are not visible to other threads (with the premise, explained later)

2, independent of the initialization of the variable copy

Threadlocal can give an initial value, and each thread will get a copy of the initialization value to ensure that different threads have a copy.

3, the state and a certain line Threads association

ThreadLocal is not used to solve the problem of shared variables, not to reconcile thread synchronization, but to facilitate the introduction of a mechanism for each thread to handle its own state, understanding this is critical to correct use of ThreadLocal
Let's look at a simple example:

Package Concurrent;import Java.util.Locale; Public classThreadlocaldemo {Private StaticThreadlocal<integer> local=NewThreadlocal<integer> () {@OverrideprotectedIntegerInitialValue() {return 0;//Initial value}    }; Public Static void Main(string[] args) {thread[] threads=Newthread[3]; for(intI=0;i<3; i++) {threads[i]=NewThread (NewRunnable () {@Override Public void Run() {intMun=local.Get(); for(intj=0;j<Ten; j + +) {mun=mun+1; } Local.Set(MUN); System. out. println (Thread.CurrentThread (). GetName () +"==="+local.Get());        }            }); } for(Thread t:threads)        {T.start (); }    }}

Run results

Thread-3===10Thread-2===10Thread-1===10

As we can see, each thread's cumulative result is 10, each thread processes its own local variable value, and the threads do not affect each other.
Now let's look at a chestnut.

Package Concurrent;import Java.util.Locale; Public classThreadlocaldemo {Private StaticNumberList numlist=NewNumberList ();Private StaticThreadlocal<numberlist> local=NewThreadlocal<numberlist> () {@OverrideprotectedNumberListInitialValue() {returnNumlist;//Initial value}    }; Public Static void Main(string[] args) {thread[] threads=Newthread[3]; for(intI=0;i<3; i++) {threads[i]=NewThread (NewRunnable () {@Override Public void Run() {numberlist list=local.Get(); for(intj=0;j< +; j + +) {list.init (); } Local.Set(list); System. out. println (Thread.CurrentThread (). GetName () +"==="+local.Get(). Num);//  }            }); } for(Thread t:threads)        {T.start (); }    }StaticClass numberlist{intNum Public void Init() {num++; }}}

Running results are not the same every time.
First time

Thread-3===2000Thread-2===2000Thread-1===3000

Second time

Thread-1===1372Thread-3===2873Thread-2===2774

Let's take another look. "Threadlocal can give an initial value, and each thread will get a copy of this initialization value." "Copy of initial value ... "It seems to think of something." Let's take a look at the places in the code above that define threadlocal.

    privatestatic ThreadLocal<NumberList> local=new ThreadLocal<NumberList>(){        @Override        protectedinitialValue() {            return numlist;//初始值已经定义好的的//          return new NumberList();每次都new一下        }    };

In the above code, we provide an initial value for our threadlocal by overriding the InitialValue function, and each thread gets a copy of the initial value. And now our initial value is a well-defined object, and num is a reference to that object. In other words our initial value is a reference. Is the referenced copy and reference pointing to the same object?

What if we want to save a NumberList object for each thread? That is to create a copy of the object instead of the object reference:

    privatestatic ThreadLocal<NumberList> local=new ThreadLocal<NumberList>(){        @Override        protectedinitialValue() {//          return numlist;//初始值已经定义好的的        returnnew NumberList();//每次都new一下        }    };

Now we should be able to understand the meaning of threadlocal local variables. Next we will look at the source of threadlocal, from the inside to reveal its mystery.

Threadlocal has an internal class threadlocalmap, the implementation of this class accounted for the entire Threadlocal class source code more than half. The role of this threadlocalmap is critical, and it is a container for threads to actually save the thread's own local variables. Each thread has its own separate instance of Threadlocalmap, and all its local variables are saved to this map. Now let's get and set from Threadlocal

 PublicT get () {//Gets the current thread of execution        ThreadT= Thread.CurrentThread ();//Gets the Threadlocalmap instance of the current threadThreadlocalmapMap =Getmap (t);//If map is not empty, it means that the thread already has a Threadlocalmap instance        if(Map != NULL) {//map All thread-local variables in the save thread, we are going to find the current thread local variableThreadlocalmap.Entry E= Map.Getentry (this);//If the current thread local variable exists in this map, its corresponding value is returned            if(E!= NULL)return(T) E.Value }//If map does not exist or the current thread local variable does not exist in map, the initial value is returned        returnSetinitialvalue (); }

To emphasize: The thread object has an attribute threadlocals of type Threadlocalmap, which is dedicated to saving all of its thread-local variables. This property is null when the thread object is initialized. Therefore, the Threadlocals property needs to be initialized for the first time that a thread object is used on a thread-local variable. Note that the "thread first uses local thread variable" and "use a thread-local thread variable for the first time" are distinguished.

Getmap Method:

//直接返回线程对象的threadLocals属性ThreadLocalMap getMap(Thread t) {        return t.threadLocals;    }

Setinitialvalue method: (Look at the chestnut before you read it)

private  T setinitialvalue  () {//get the initialization value, InitialValue is the method we covered previously  T value  = InitialValue (); Thread t = Thread.CurrentThread (); Threadlocalmap map = getmap (t); //if map is not empty, put the initialization value into the Threadlocalmap object of the current thread  if  (Map! = null ) map. set  (this , value ); else  //the current thread uses local thread variables for the first time, the map needs to be initialized  Createmap (t, value ); //returns the initialization value of  return  value ; }

Let's take a look at the Set method

publicvoidsetvalue) {        Thread t = Thread.currentThread();        ThreadLocalMap map = getMap(t);        ifnull)            map.set(thisvalue);        //说明线程第一次使用线程本地变量(注意这里的第一次含义)        else            value);    }

Summary
Threadlocal is a good idea to solve thread safety problems by providing a separate copy of the variable for each thread to solve the conflicting problem of variable concurrency access. In many cases, threadlocal is easier and more convenient than using the synchronized synchronization mechanism to solve thread safety problems, and results programs have higher concurrency.

Deep learning to understand java-threadlocal

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.