inheritablethreadlocal Realization Principle

Source: Internet
Author: User
Tags static class thread class

Introduce inheritablethreadlocal before, assume to ThreadLocal already have certain understanding, for instance basic concept, principle, if not, can refer to: Java Multithreading: ThreadLocal keyword.

Here is a review of the ThreadLocal principle, because it will be of great help to the understanding of inheritablethreadlocal: Each thread has a threadlocalmap type of threadlocals attribute. The Threadlocalmap class is equivalent to a map,key is ThreadLocal itself, value is our values. When we pass Threadlocal.set (new Integer (123)); , we put a key value pair in the Threadlocals attribute in this thread, and the key is this threadlocal.set (new Integer (123)); The Threadlocal,value is the value. When we pass the Threadlocal.get () method, we first get the threadlocals attribute of the thread according to this thread, and then because this property is placed in the key value pair, we can get the value according to the key threadlocal. Note that this time the key threadlocal is the same as the key threadlocal our set method, so we can get the same value.

Ps: If this principle is not clear, then the following estimates are more difficult to understand, so the proposal completely understand this principle. inheritablethreadlocal Concept

As we can see from the above introduction, we actually get the threadlocals of the thread according to Thread.CurrentThread (), thus further getting the value we had previously set well. So if we open a new thread, this time, because the Thread.CurrentThread () has changed, causing the threadlocals to be different, we didn't put a value in the threadlocals of the new thread, so I passed Threadlocal.get () method is not possible to get the value. For example, the following code:

public class Test {public

    static threadlocal<integer> ThreadLocal = new threadlocal<integer> ();

    public static void Main (String args[]) {
        threadlocal.set (new Integer (123));

        Thread thread = new Mythread ();
        Thread.Start ();

        System.out.println ("main =" + Threadlocal.get ());
    }

    Static class Mythread extends thread{
        @Override public
        void Run () {
            System.out.println ("mythread =" + Threadlocal.get ());}}

The output is:

Main = 123
Mythread = null

Then how to solve this time. Inheritablethreadlocal can solve this problem. Let's look at an official introduction to it:

* This class extends <tt>ThreadLocal</tt> to provide inheritance of the values
 * from parent thread to child T Hread:when a child thread are created, the
 * child receives initial values to all inheritable thread-local C4/>* for which the parent has values.  Normally the child's values would be
 * Identical to the parent ' s; however, the child's value can be made a
 * arbit Rary function of the parent ' s by overriding the <tt>childValue</tt>
 * to this class.

In other words, we put the above

public static threadlocal<integer> ThreadLocal = new threadlocal<integer> ();

Change into

public static threadlocal<integer> ThreadLocal = new inheritablethreadlocal<integer> ();

Run again, and there will be results:

Main = 123
Mythread = 123

That is, the child thread, or the new thread, gets the value. So, this is how to achieve it, key has changed, why can still get it. inheritablethreadlocal principle

We can first browse through what's in the Inheritablethreadlocal class:

public class Inheritablethreadlocal<t> extends threadlocal<t> {
    protected T Childvalue (t parentvalue) { return
        parentvalue;
    }
    Threadlocalmap Getmap (Thread t) {return
       t.inheritablethreadlocals;
    }
    void Createmap (Thread T, T firstvalue) {
        t.inheritablethreadlocals = new Threadlocalmap (this, firstvalue);
}

In fact, rewrite the 3 methods.

First, when we call the Get method, because the subclass is not overridden, we call the Get method of the parent class:

Public T get () {
    Thread t = thread.currentthread ();
    Threadlocalmap map = getmap (t);
    if (map!= null) {
        Threadlocalmap.entry e = Map.getentry (this);
        if (e!= null) {
            @SuppressWarnings ("unchecked")
            T result = (t) e.value;
            return result;
        }
    return Setinitialvalue ();
}

There will be a thread.currentthread (), Getmap (t) method, so you will get this thread threadlocals. However, since subclasses inheritablethreadlocal rewrite the Getmap () method, and then look at the above code, we can see:
Actually not get threadlocals, but get inheritablethreadlocals. Inheritablethreadlocals has not mentioned before, in fact it is also a thread class of a threadlocalmap type of attributes, the following thread class part of the code:

Threadlocal.threadlocalmap threadlocals = null;
Threadlocal.threadlocalmap inheritablethreadlocals = null;

So, here's a look at the inheritablethreadlocal rewrite, and it feels like inheritablethreadlocals and threadlocals are almost exactly the same, just changing the name and then why on Earth is it in the new thread Threadlocal.get () method can also get the value.

At this time to pay attention to the Childvalue method, we can look at its official description:

* Computes the child's initial value for this inheritable thread-local
 * variable as a function of the parent ' s value At the time the ' child '
 * thread is created.  This are called from within the parent * thread before the ' child ' is
 started.

This time, you see, is not in the creation of the thread when the hands and feet, do some of the value of the transfer, or here to use the inheritablethreadlocals and so on.

In fact, yes: The key is thread thread = new Mythread (); The key is thread thread = new Mythread (); The key is thread thread = new Mythread ();

This is not a simple new operation. When we are new to a thread:

Public Thread () {
    init (null, NULL, "thread-" + nextthreadnum (), 0);
}

And then:

private void Init (Threadgroup g, Runnable Target, String name,
                      long stacksize) {
    init (g, Target, name, StackSize, NULL);

And then:

private void Init (Threadgroup g, Runnable Target, String name,
                      long stacksize, AccessControlContext acc) {
     ...
    if (parent.inheritablethreadlocals!= null)
        this.inheritablethreadlocals =
            Threadlocal.createinheritedmap (parent.inheritablethreadlocals);
        /* Stash The specified stack size in case the VM cares
        /this.stacksize = stacksize;
    ......
    }

There was a phrase ' threadlocal.createinheritedmap (parent.inheritablethreadlocals); ' And then

Static Threadlocalmap Createinheritedmap (Threadlocalmap parentmap) {return
    new Threadlocalmap (PARENTMAP);
}

Continue tracking:

private
    Threadlocalmap (Threadlocalmap parentmap) {entry[] parenttable = parentmap.table;
    int len = parenttable.length;
    Setthreshold (len);

    Table = new Entry[len];
        for (int j = 0; J < Len; J +) {Entry e = parenttable[j]; if (e!= null) {@SuppressWarnings ("unchecked") threadlocal<object> key = (threadlocal<ob
            ject>) E.get ();
                if (key!= null) {Object value = Key.childvalue (E.value);
                Entry C = new Entry (key, value);
                int h = key.threadlocalhashcode & (len-1);
                    while (Table[h]!= null) H = Nextindex (h, Len);
                    TABLE[H] = c;
                size++; }
            }
        }
    }

When we create a new thread, the X,X thread will have a threadlocalmap type of inheritablethreadlocals, because it is a property of the thread class.

And then

First get these values that the current thread stores, such as entry[] parenttable = parentmap.table;. And then, through a for loop, constantly copy these values from the current thread into the inheritablethreadlocals of our newly created thread x. That's it, it's OK.

So what would be the result of that?

The result is that we have a value in the inheritablethreadlocals variable of the new thread x we created. So I call the Threadlocal.get () method in the new thread x, first I get the inheritablethreadlocals of the new thread X, and then, according to the threadlocal in Threadlocal.get (), will be able to get this value.

This avoids the threadlocals in the new thread. It is because there is no thing, so you can not get the value.

So that's how the whole inheritablethreadlocal works. The summary first understands why the value is not available in the new thread because we actually get the threadlocals of the thread based on Thread.CurrentThread (), which further gets the value we previously set well. So if we open a new thread, this time, because the Thread.CurrentThread () has changed, causing the threadlocals to be different, we didn't put a value in the threadlocals of the new thread, so I passed Threadlocal.get () method is not possible to get the value. The solution is that in the new thread, we want to copy the Threadlocals value of the parent thread to the threadlocals in the new thread. In this way, the threadlocals that we get in the new thread will have something, and then through the threadlocal in the  threadlocal.get ()  , we get the value. reference Java concurrency in practice reading notes---The difference between the threadlocal principle threadlocal and synchronized?

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.