InheritableThreadLocal的作用: 当我们需要在子线程中使用父线程中的值得时候我们就可以像使用ThreadLocal那样来使用InheritableThreadLocal了。
首先我们来看一下InheritableThreadLocal的jdk源码:
package java.lang; import java.lang.ref.*; 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); } }
这段代码就是InheritableThreadLocal的完整源码(删除了很长的注释)。
首先我们可以看到它是继承ThreadLocal类的,然后提供了:
protected T childValue(T parentValue){}方法,这就是InheritableThreadLocal的关键所在,它提供了这个方法,返回父线程中的值,如果还需要在父线程上添加值则可以重写childValue方法。
package InheritableThreadLocal; import java.util.Date; public class InheritableThreadLocaExt extends InheritableThreadLocal{ protected Object initialValue() { return new Date().getTime(); } protected Object childValue(Object parentValue) { return parentValue+"对继承值进行修改"; } } package InheritableThreadLocal; public class tool { public static InheritableThreadLocaExt t=new InheritableThreadLocaExt(); } package InheritableThreadLocal; public class MyThread extends Thread{ public void run() { try { for(int i=0;i<10;i++) { System.out.println("在线程A中:"+tool.t.get()); sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } } } package InheritableThreadLocal; public class test { public static void main(String[] args) { try { for(int i=0;i<10;i++) { System.out.println("主线程中值:"+tool.t.get()); Thread.sleep(100); } Thread.sleep(5000); MyThread thread=new MyThread(); thread.start(); }catch(InterruptedException e){ e.printStackTrace(); } } }
运行输出:
主线程中值:1508210392057
主线程中值:1508210392057
主线程中值:1508210392057
主线程中值:1508210392057
主线程中值:1508210392057
主线程中值:1508210392057
主线程中值:1508210392057
主线程中值:1508210392057
主线程中值:1508210392057
主线程中值:1508210392057
在线程A中:1508210392057对继承值进行修改
在线程A中:1508210392057对继承值进行修改
在线程A中:1508210392057对继承值进行修改
在线程A中:1508210392057对继承值进行修改
在线程A中:1508210392057对继承值进行修改
在线程A中:1508210392057对继承值进行修改
在线程A中:1508210392057对继承值进行修改
在线程A中:1508210392057对继承值进行修改
在线程A中:1508210392057对继承值进行修改
在线程A中:1508210392057对继承值进行修改
是不是有一个疑问,为什么子线程能获取父线程的数据?
我们可以看到InheritableThreadLocal重写了getMap方法和createMap方法,上一节讲ThreadLocal的时候我们知道,ThreadLocal的值是存储在一个叫ThreadLocals的变量中,但是现在返回一个InheritableThreadLocals,这个变量和ThreadLocals是一模一样的只是名字换了,那么究竟 为什么在新的 线程中 通过 threadlocal.get() 方法还能得到值呢?
我们看childValue方法可以猜测到可能在线程创建的时候,做了一些手脚,做了一些值得传递。
我们打开Thread类的源码的时候可以发现 :
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
所以当我们创建一个子线程的时候,他就存在一个和ThreadLocals的一样的InheritableThreadLocal变量,再往下看:
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, . . if (inheritThreadLocals && parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
重点是以下这段代码:
if (inheritThreadLocals && parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
继续看:
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++; } } } }
有这段代码,先得到父线程(也就是当前执行的线程)的值,然后用for循环一个个的将父线程中的值放入我们新创建的值中。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍Java多线程之多线程异常捕捉,包括了Java多线程之多线程异常捕捉的使用技巧和注意事项,需要的朋友参考一下 一:为什么要单独讲多线程的异常捕捉呢? 先看个例子: 在run中手动抛出了一个运行时异常,在main中启动线程,catch语句块中捕捉下异常,捕捉到打印一句话。运行结果如下图: 发现异常被抛到了控制台,没有打印catch块中的语句。 结论:多线程运行不能按照顺
本文向大家介绍java多线程编程之Synchronized块同步方法,包括了java多线程编程之Synchronized块同步方法的使用技巧和注意事项,需要的朋友参考一下 文章分享了4个例子对synchronized的详细解释 1、是否加synchronized关键字的不同 加了synchronized关键字的输出结果如下 会先输出一组0-4,接着再输出下一组,两个线程顺序执行 excute:0
其实创建线程之后,线程并不是始终保持一个状态的,其状态大概如下: New 创建 Runnable 就绪。等待调度 Running 运行 Blocked 阻塞。阻塞可能在 Wait Locked Sleeping Dead 消亡 线程有着不同的状态,也有不同的类型。大致可分为: 主线程 子线程 守护线程(后台线程) 前台线程 简单了解完这些之后,我们开始看看具体的代码使用了。 1、线程的创建 Pyt
如果以下代码在多线程应用程序中可以工作,您可以帮助我吗。 这是我的Java脚本,将由Nashorn评估 这就是我创建脚本引擎的方式 在使用Testng进行测试时,此操作不会出现任何错误 测试结果1-请注意,有些数据是重复的 但是,如果我添加"并行=true"到@DataProvider我的脚本开始失败 测试结果2-请注意,重复一些数据,以表明相同的参考编号可能在测试过程中随机失败 有人可以确认我是
本文向大家介绍python多线程socket编程之多客户端接入,包括了python多线程socket编程之多客户端接入的使用技巧和注意事项,需要的朋友参考一下 Python中实现socket通信的服务端比较复杂,而客户端非常简单,所以客户端基本上都是用sockct模块实现,而服务 端用有很多模块可以使用,如下: 1、客户端 2、SocketServer模块 为了能够让多个客户端同时接入服务并进行通
本文向大家介绍linux多线程编程(五),包括了linux多线程编程(五)的使用技巧和注意事项,需要的朋友参考一下 线程 线程是计算机中独立运行的最小单位,运行时占用很少的系统资源。可以把线程看成是操作系统分配CPU时间的基本单元。一个进程可以拥有一个至多个线程。它线程在进程内部共享地址空间、打开的文件描述符等资源。同时线程也有其私有的数据信息,包括:线程号、寄存器(程序计数器和堆栈指针)、堆