Foreword
Introduced earlier ThreadLocal usage, by threadLocal a value in the same thread pass, but father and son in the thread can not be passed by value, and because it is not the same thread, so the corresponding ThreadLocalMap is not the same
Examples
ThreadLocal example
public class ThreadLocalTest {
public static ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static String get() {
return threadLocal.get();
}
public static void set(String value) {
threadLocal.set(value);
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
final int j = i;
ThreadLocalTest.set("ye");
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ":" + ThreadLocalTest.get());
}
});
t.start();
}
}
}
复制代码
result:
InheritableThreadLocal examplepublic class InheritableThreadLocalTest {
public static ThreadLocal<String> threadLocal = new InheritableThreadLocal<>();
public static String get() {
return threadLocal.get();
}
public static void set(String value) {
threadLocal.set(value);
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
InheritableThreadLocalTest.set("ye");
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ":" + InheritableThreadLocalTest.get());
}
});
t.start();
}
}
}
复制代码
result:
Resolve
InheritableThreadLocal inherited ThreadLocal look at his set method, set by calling the set method 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);
}
复制代码
createMap calls itself overridden
void createMap(Thread t, T firstValue) {
t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
}
复制代码
See above discovery and the ThreadLocal createMap almost initialize a ThreadLocalMap, just assigned to the inheritableThreadLocals, and ThreadLocal assigned to the threadLocals
Continue to look at the get method, get method is invoked ThreadLocal get methods
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();
}
复制代码
The difference is that getMap call is overridden method InheritableThreadLocal
ThreadLocalMap getMap(Thread t) {
return t.inheritableThreadLocals;
}
复制代码
Because the assignment to the set time is t.inheritableThreadLocals, so take the map of the time it was taken from t.inheritableThreadLocals
After reading the set and get methods, the only difference is where the map is not the same access, but can not see it different from the other, but a change only one variable, and how he was not the same ThreadLocal, is how to complete the value of parent-child thread That depends Thread pass it initializes, look at the Thread class constructor you will see invokes an init method
Thread init method
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
/* Determine if it's an applet or not */
/* If there is a security manager, ask the security manager
what to do. */
if (security != null) {
g = security.getThreadGroup();
}
/* If the security doesn't have a strong opinion of the matter
use the parent thread group. */
if (g == null) {
g = parent.getThreadGroup();
}
}
/* checkAccess regardless of whether or not threadgroup is
explicitly passed in. */
g.checkAccess();
/*
* Do we have the required permissions?
*/
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
/* Set thread ID */
tid = nextThreadID();
}
复制代码
The above method is mainly to see
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
复制代码
inheritThreadLocals is the reference method, only to see the constructor Thread (Runnable target, AccessControlContext acc) is false, the rest of the construction methods are true, it is true that we pass here
Thread(Runnable target, AccessControlContext acc) {
init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
}
复制代码
Thread parent = currentThread (); in this case is our main thread, because we are using in the main there is InheritableThreadLocalTest.set ( "ye"); so we put ThreadLocalMap assigned to the inheritableThreadLocals sum will go this.inheritableThreadLocals = ThreadLocal.createInheritedMap (parent.inheritableThreadLocals); the this new child thread of the current
Then we must look inheritableThreadLocals child thread is how the assignment
static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
return new ThreadLocalMap(parentMap);
}
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<Object>) 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++;
}
}
}
}
复制代码
The code is very simple, is to get ThreadLocalMap parent thread, and copy (shallow copy, copy reference), such child threads have a corresponding ThreadLocalMap inheritableThreadLocals, so that the same value can be taken and the parent thread by ThreadLocalMap
summary
InheritableThreadLocal inheritance ThreadLocal, ThreadLocal so usage and, as the only difference is ThreadLocal using a ThreadLocal variable using a ThreadLocal.ThreadLocalMap threadLocals InheritableThreadLocal use the ThreadLocal.ThreadLocalMap inheritableThreadLocals variable but they are ThreadLocalMap, so the get and set essentially no difference the InheritableThreadLocal reason why his son can support direct transfer thread is init copied when the parent thread new thread of the ThreadLocalMap to inheritableThreadLocals child thread in