ThreadLocal and threadlocal

Source: Internet
Author: User

ThreadLocal and threadlocal
Preface ThreadLocal creates a copy of the variable in each thread. Therefore, each thread can access its own internal copy variable without interfering with each other. This article describes how to use ThreadLocal and its internal implementation mechanism based on actual scenarios. In application scenarios, the data of the Parameter object needs to be used in multiple modules. If Parameter transmission is adopted, the coupling between modules is obviously increased. First, let's take a look at how ThreadLocal can be used to share data between modules.

Class Parameter {private static ThreadLocal <Parameter> _ parameter = new ThreadLocal <> (); public static Parameter init () {_ parameter. set (new Parameter ();} public static Parameter get () {_ parameter. get ();}... omitted variable declaration}
From the Thread perspective, each Thread holds a reference to the ThreadLocalMap instance. The ThreadLocalMap instance is equivalent to the local variable space of the Thread and stores the data of each Thread, as shown below:

 

The EntryEntry inherits from the WeakReference class and is the data structure that stores the private variables of the thread. The ThreadLocal instance is referenced. This means that if the ThreadLocal instance is null, the corresponding Entry can be deleted from the table.
class Entry extends WeakReference<ThreadLocal<?>> { Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; }}
ThreadLocalMap uses the table array to store the Entry. The default size is INITIAL_CAPACITY (16). First, several parameters are introduced:
  • Size: number of elements in the table.
  • Threshold: 2/3 of the table size. When size> = threshold, traverse the table and delete the element whose key is null. If the deleted size> = threshold * 3/4, you need to resize the table.
ThreadLocal. set () Implementation
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;}
From the code above: Next, let's look at how the Entry stores the table array:
private void set(ThreadLocal<?> key, Object value) { Entry[] tab = table; int len = tab.length; int i = key.threadLocalHashCode & (len-1);  for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { ThreadLocal<?> k = e.get(); 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();}
  • If k is the same as the current ThreadLocal instance, modify the value and return it.
  • If k is null, it indicates that f is a stale element. Call the replaceStaleEntry method to delete all old elements in the table (that is, the entry reference is null), insert new elements, and return.
  • Otherwise, find the next element f through the nextIndex method and proceed to step 3.
  1. If f = null, the Entry is added to the I position of the table.
  2. You can use cleanSomeSlots to delete old elements. If no elements in the table are deleted, You need to determine whether to scale up in the current situation.
If the number of elements in the table reaches 3/4 of the threshold value of threshold, the table will be resized. The process is simple:
private void resize() { Entry[] oldTab = table; int oldLen = oldTab.length; int newLen = oldLen * 2; Entry[] newTab = new Entry[newLen]; int count = 0;  for (int j = 0; j < oldLen; ++j) { Entry e = oldTab[j]; if (e != null) { ThreadLocal<?> k = e.get(); if (k == null) { e.value = null; // Help the GC } else { int h = k.threadLocalHashCode & (newLen - 1); while (newTab[h] != null) h = nextIndex(h, newLen); newTab[h] = e; count++; } } }  setThreshold(newLen); size = count; table = newTab;}
ThreadLocal. get () Implementation
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();} private Entry getEntry(ThreadLocal<?> key) { int i = key.threadLocalHashCode & (table.length - 1); Entry e = table[i]; if (e != null && e.get() == key) return e; else return getEntryAfterMiss(key, i, e);}
Obtain the threadLocals of the current thread.

Related Article

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.