多线程进阶InheritableThreadLocal
来源:互联网 发布:淘宝双11后生意不好 编辑:程序博客网 时间:2024/04/30 00:58
上篇说的是ThreadLocal,如果对ThreadLocal足够了解的话,InheritableThreadLocal也很好理解。InheritableThreadLocal类继承于ThreadLocal类,所以它具有ThreadLocal类的特性,但又是一种特殊的ThreadLocal,其特殊性在于InheritableThreadLocal变量值会自动传递给所有子线程,而普通ThreadLocal变量不行,那么子线程是否可以修改InheritableThreadLocal变量值然后反向传递给主线程了,答案是对于引用类型来说,其内部的属性改变是可以传递给主线程的,对于基本数据类型以及String,Integer等包装类型来说是不可以的,原因是子线程的变量来源于父线程变量的浅拷贝,首先来个例子:
package com.lzzl.thread10;public class Person { private String name; private int id; @Override public String toString() { return "Person [name=" + name + ", id=" + id + "]"; } public Person(){ } public Person(String name, int id) { super(); this.name = name; this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; }}
package com.lzzl.thread10;public class MyThreadLocal extends ThreadLocal<Person>{ @Override protected Person initialValue() { // TODO Auto-generated method stub return new Person("初始值",0); }}package com.lzzl.thread10;public class MyInheritableThreadLocal extends InheritableThreadLocal<Person>{ @Override protected Person initialValue() { // TODO Auto-generated method stub return new Person("in初始值",0); }}package com.lzzl.thread10;public class Tools { public static MyThreadLocal t1 = new MyThreadLocal(); public static MyInheritableThreadLocal t2 = new MyInheritableThreadLocal();}
package com.lzzl.thread10;public class Run { public static void main(String[] args) { Tools.t2.set(new Person("inmain",1));//执行步骤1 new Thread(new Runnable() { public void run() { System.out.println("线程A获t2得的值"+Tools.t2.get());//执行步骤4 Tools.t2.get().setName("---main");//执行步骤5,这里修改了存入的变量的属性 System.out.println("线程A修改t2的值");//执行步骤6 System.out.println("线程A获得t2的值"+Tools.t2.get());//执行步骤7 } },"A").start(); System.out.println("main线程获得t2的值"+Tools.t2.get());//执行步骤2 try { Thread.sleep(3000);//执行步骤3 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("main线程获得t2的值"+Tools.t2.get()); }}
输出
线程A获t2得的值Person [name=inmain, id=1]
线程A修改t2的值
main线程获得t2的值Person [name=inmain, id=1]
线程A获得t2的值Person [name=—main, id=1]
main线程获得t2的值Person [name=—main, id=1]
到这里已经看出的子线程修改变量的属性反映到了主线程之中
来看看其原理吧,贴上源代码
public class InheritableThreadLocal<T> extends ThreadLocal<T> { /** * 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 method is called from within the parent * thread before the child is started. * <p> * This method merely returns its input argument, and should be overridden * if a different behavior is desired. *//这里可以对从父线程得到的变量进行自己的改变 * @param parentValue the parent thread's value * @return the child thread's initial value */ protected T childValue(T parentValue) { return parentValue; } /** * Get the map associated with a ThreadLocal. * * @param t the current thread */ ThreadLocalMap getMap(Thread t) { return t.inheritableThreadLocals; } /** * Create the map associated with a ThreadLocal. * * @param t the current thread * @param firstValue value for the initial entry of the table. * @param map the map to store. */ void createMap(Thread t, T firstValue) { t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue); }}
publicclass Thread implements Runnable {ThreadLocal.ThreadLocalMap threadLocals = null;ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); } private void init(ThreadGroup g, Runnable target, String name, long stackSize) { if (name == null) { throw new NullPointerException("name cannot be null"); } Thread parent = currentThread();//parent为当前线程 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(); this.name = name.toCharArray(); if (security == null || isCCLOverridden(parent.getClass())) this.contextClassLoader = parent.getContextClassLoader(); else this.contextClassLoader = parent.contextClassLoader; this.inheritedAccessControlContext = AccessController.getContext(); this.target = target; setPriority(priority); if (parent.inheritableThreadLocals != null)//拷贝父线程的inheritableThreadLocals this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; /* Set thread ID */ tid = nextThreadID(); }static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) { return new ThreadLocalMap(parentMap); } 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; } } private ThreadLocalMap(ThreadLocalMap parentMap) {//拷贝父线程中的map 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) { ThreadLocal key = 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++; } } } } }}
阅读全文
0 0
- 多线程进阶InheritableThreadLocal
- Java多线程之----InheritableThreadLocal
- 多线程编程之InheritableThreadLocal
- Java 多线程:InheritableThreadLocal 实现原理
- Java 多线程:InheritableThreadLocal 实现原理
- Java 多线程:InheritableThreadLocal 实现原理
- InheritableThreadLocal
- Java多线程值继承(InheritableThreadLocal )
- Java 多线程8:InheritableThreadLocal 实现原理
- Java 多线程学习笔记(十) InheritableThreadLocal的使用
- Java多线程之ThreadLocal和InheritableThreadLocal的使用
- ThreadLocal & InheritableThreadLocal
- Java多线程编程3--线程间通信--类ThreadLocal与类InheritableThreadLocal的使用
- 多线程进阶代码一
- 多线程进阶代码二
- 多线程进阶代码三
- 多线程进阶代码四
- 多线程菜鸟进阶 一
- Azure Cosmos DB技术性解读
- Ubuntu系统下装Atheros网卡搜索不到wifi问题
- VisualSVN错误 Cannot query proxy blanket解决办法
- java算法基础--二分查找
- Android Framework中引入第三方框架jar包
- 多线程进阶InheritableThreadLocal
- 三分熟博士生の阅读理解与问答数据集 | 论文集精选 #03
- Qt排序qSort使用方法
- Oracle之 【RANDOM】使用dbms_random.string产生随机字符串的用法及应用
- 微服务:spring-cloud-archaius 起步
- 94. Binary Tree Inorder Traversal
- Android模拟器上的本机IP地址
- netty实现http服务器
- [NOIP2017模拟][SCOI2005][bzoj1084]最大子矩阵