Java's threadlocal detailed

Source: Internet
Author: User
Tags thread class

I. Introduction of Threadlocal

threadlocal is a local variable of a thread that is held separately by each thread, which other threads cannot access , usually a private static field in a class.

We know that sometimes a variable of an object is accessed by multiple threads, then there is a thread security problem, and of course we can use the Synchorinized keyword to lock the variable and synchronize it, thus restricting only one thread to use this variable, but locking can greatly affect program execution efficiency. In addition, we can use threadlocal to resolve access violation issues for a variable.

When using threadlocal to maintain variables, provide a separate copy of the variable for each thread that uses the variable, that is, there is a variable inside each thread so that multiple threads accessing the variable do not affect each other, so they use a copy of the variable that they copied from memory. This does not present a thread-safety issue and does not affect the execution performance of the program.

Note, however, that although threadlocal is able to solve the above problem, due to the creation of replicas in each thread, it is important to consider the consumption of resources, such as memory usage, which is larger than threadlocal.

Ii. threadlocal Source Code Analysis (1) Threadlocal method

Several methods of ThreadLocal: ThreadLocal can store any type of variable object, and get returns an object, but we can use generics to make a type of storage object.

public T get() { } // 用来获取ThreadLocal在当前线程中保存的变量副本public void set(T value) { } //set()用来设置当前线程中变量的副本public void remove() { } //remove()用来移除当前线程中变量的副本protected T initialValue() { } //initialValue()是一个protected方法,一般是用来在使用时进行重写的
(2) Threadlocal implementation principle 1. Internal structure

Thread internally is threadlocalmap to maintain the threadlocal variable table, there is a threadlocals variable in the thread class, is the Threadlocalmap type, It is the threadlocal variable that stores itself for each thread.

ThreadLocal.ThreadLocalMap threadLocals = null;

Threadlocalmap is the inner class defined in the Threadlocal class, and its function is to store the thread's local variables. Threadlocalmap is a threadlocal reference as a key, with local variables as values, stored in threadlocalmap.entry (a data structure that stores key values). This is because within each thread, there may be multiple threadlocal variables

static class ThreadLocalMap { static class Entry extends WeakReference<ThreadLocal<?>> {        /** The value associated with this ThreadLocal. */        Object value;        Entry(ThreadLocal<?> k, Object v) {            super(k);            value = v;        }    }}
2. Calling the procedure

Initially, in thread, Threadlocals is empty, and when the Get () method or set () method is called through the threadlocal variable, the threadlocals in the thread class is initialized. And with the current threadlocal variable as the key value, to threadlocal the copy variable to save as value, save to Threadlocals.
Then in the current thread, if you want to use a copy variable, you can find it in the threadlocals by the Get method

Attention:

A set is required before a get is made, otherwise a null pointer exception is reported;

You must override the InitialValue () method if you want to have normal access without calling set before get.
  

The set (T value) method of the Threadlocal
public void set(T value) {  // 获得当前线程Thread t = Thread.currentThread();  // 获得当前线程的 ThreadLocalMap 引用,详细见下ThreadLocalMap map = getMap(t);  // 如果不为空,则更新局部变量的值if (map != null)  map.set(this, value);  //如果不是第一次使用,先进行初始化else  createMap(t, value);}
Set of inner class Threadlocalmap (threadlocal<?> key,object value)
    private void set(ThreadLocal<?> key, Object value) { Entry[] tab = table; int len = tab.length;    // Hash 寻址,与table数组长度减1(二进制全是1)相与,所以数组长度必须为2的次方,减小hash重复的可能性 int i = key.threadLocalHashCode & (len-1);   //从hash值计算出的下标开始遍历 for (Entry e = tab[i];      e != null;      e = tab[i = nextIndex(i, len)]) {   //获得该Entry的键   ThreadLocal<?> k = e.get();    //如果键和传过来的相同,覆盖原值,也说明,一个ThreadLocal变量只能为一个线程保存一个局部变量   if (k == key) {     e.value = value;     return;   }   // 键为空,则替换该节点   if (k == null) {     replaceStaleEntry(key, value, i);     return;   } } tab[i] = new Entry(key, value); int sz = ++size;   //是否需要扩容 if (!cleanSomeSlots(i, sz) && sz >= threshold)   rehash();}

It can be seen that THREADLOCALMAP uses linear detection and hashing to solve the problem of hash conflict. That is, if a hash of the array subscript is occupied, that is, the hash value is repeated, then on the basis of the subscript plus 1 test the next subscript, until a null value is found. For example, the hash calculates that the subscript i is 6,table[6] already has value, then try Table[7] is occupied, and so on, until a null value is found. The above is the method of saving thread local variables.

The Get () method of the Theadlocal
public T get() {  //获得当前线程    Thread t = Thread.currentThread();  //得到当前线程的一个threadLocals 变量ThreadLocalMap map = getMap(t);if (map != null) {  // 如果不为空,以当前ThreadLocal为主键获得对应的Entry  ThreadLocalMap.Entry e = map.getEntry(this);  if (e != null) {    @SuppressWarnings("unchecked")    T result = (T)e.value;    return result;  }}  //如果值为空,则进行初始化return setInitialValue();}
Threadlocal's Setinitialvalue () method
private T setInitialValue() {  //获得初始默认值T value = initialValue();  //得到当前线程Thread t = Thread.currentThread();  // 获得该线程的ThreadLocalMap引用ThreadLocalMap map = getMap(t);  //不为空则覆盖if (map != null)    map.set(this, value);else      //若是为空,则进行初始化,键为本ThreadLocal变量,值为默认值    createMap(t, value);}// 默认初始化返回null值,这也是 下面demo 为什么需要重写该方法的原因。如果没有重写,第一次get()操作获得的线程本地变量为null,需要进行判断并手动调用set()进行初始化protected T initialValue() {    return null;}
Third, Demo

Below is an instance of Threadlocal, where two tasks share the same variable, and both tasks set the variable to a thread-private variable, so that although both tasks "hold" the same variable, they each hold a copy of the variable. Therefore, when a thread modifies the variable, it does not affect the value of the variable in another process.

Package Thread. Threadlocaltest;import java.util.random;import java.util.concurrent.timeunit;/*** Created by StoneGeek on 2018/8/1.* Blog Address: Http://www.cnblogs.com/sxkgeek*/public class ThreadLocalDemo2 implements Runnable {//General ThreadLocal is set to static 。 It's just a portal to set local variables for a thread, and multiple threads need only one entry private static threadlocal<student> localstudent = new ThreadLocal () {///general overrides the initial    Analysis of the source code will explain why @Override public Student InitialValue () {return new Student ();    }};p rivate Student Student = null; @Overridepublic void Run () {String threadname = Thread.CurrentThread (). GetName ();    System.out.println ("" "+ ThreadName +" ": Is running!");    Random ramdom = new Random ();    Randomly generates a variable int age = Ramdom.nextint (100);    System.out.println ("" "+ ThreadName +" ": Set Age to:" + age);    Get thread local variable, change attribute value Student stu = Getstudent ();    Stu.setage (age);    System.out.println ("" "+ ThreadName +" ": The first time the age value is read:" + stu.getage ()); try {TimeUnit.SECONDS.sleeP (2);    } catch (Interruptedexception e) {e.printstacktrace (); } System.out.println ("" "+ ThreadName +" ": The second read of the age value is:" + stu.getage ());} Public Student getstudent () {Student = Localstudent.get ();//If you do not override the initialization method, you need to determine whether it is empty, and then manually assign a value to the threadlocal, otherwise it will report a null pointer    Exception//if (student = = null) {//student = new Student ();//Localstudent.set (student);/} return student;}    public static void Main (string[] args) {ThreadLocalDemo2 ll = new ThreadLocalDemo2 ();    thread T1 = new Thread (ll, "Thread 1");    Thread t2 = new Thread (ll, "Thread 2");    T1.start (); T2.start ();}} Console print: "Thread 2": Is running! "Thread 1": Is running! "Thread 1": Set Age to:67 "Thread 2": Set Age To:4 "Thread 1": The first read of the age value is: 67 "Thread 2": The first time the age to read Value: 4 "Thread 1": The second read of the age value is: 67 "Thread 2": The second read of the Age value is: 4
Iv. Application Scenarios

The most common threadlocal usage scenarios are
Used to solve database connection, session management and so on.

Database connection
Class A implements Runnable{private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() {    public Connection initialValue() {            return DriverManager.getConnection(DB_URL);    }};public static Connection getConnection() {       return connectionHolder.get();}}
Session Management
private static final ThreadLocal threadSession = new ThreadLocal();public static Session getSession() throws InfrastructureException {    Session s = (Session) threadSession.get();    try {        if (s == null) {            s = getSessionFactory().openSession();            threadSession.set(s);        }    } catch (HibernateException ex) {        throw new InfrastructureException(ex);    }    return s;}

Java's threadlocal detailed

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.