前言
ThreadLocal是用于存储线程在任务执行过程便于获取参数和设置参数的线程变量,它是跟线程紧密相关的;它的出现是为了解决多线程环境下的变量访问并发问题;所以单线程的任务或进程用不着它,直接用全局实例变量或类变量即可。
一、ThreadLocal实例
线程本地变量于我而言,像是开启进入JAVA世界另一维度空间的钥匙。
package com.zte.sunquan.demo.thread.local;
/**
* ThreadLocalTest class
*
* @author 10184538
* @date 2019/2/21
*/
public class ThreadLocalTest {
private static final ThreadLocal<String> nameThreadLocal = new ThreadLocal<String>() {
@Override
protected String initialValue() {
return "sunquan";
}
};
public static void main(String[] args) throws InterruptedException {
nameThreadLocal.set("abc");
Thread th1 = new Thread(() -> {
//sunquan
System.out.println(Thread.currentThread().getName() + ":" + nameThreadLocal.get());
});
th1.start();
//abc
System.out.println(Thread.currentThread().getName() + ":" + nameThreadLocal.get());
Thread.sleep(1000);
}
}
打印结果:
main:abc
Thread-0:sunquan
上面示例代码中定义了线程本地变量nameThreadLocal,虽然在MAIN线程中设置了变量值为abc,但线程thread-0打印的结果为sunquan,说明ThreadLocal线程变量在线程间相互隔离互不干扰。
二、子父线程的变量共享
在应用系统开发过程中存在子父线程变量共享的场景,如上面的示例,thread-0是main线程的子线程。
对Java中的线程,父线程的概念,只是一种逻辑称呼,创建线程的当前线程就是新线程的父线程,新线程的一些资源来自于这个父线程
线程子父关系
那子父线程是如何定义形成的,在JAVA的Thread类源中:
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
最终在方法中有父线程的描述:
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
Thread parent = currentThread();
即调用new Thread创建该线程的线程,即为该线程的父线程,注意与声明处没有关系。
JDK中提供了InheritableThreadLocal用于实现该需求
ITL使用
代码示例与上节一致,只是将线程本地变量类名换成InheritableThreadLocal
package com.zte.sunquan.demo.thread.local;
/**
* ThreadLocalTest class
*
* @author 10184538
* @date 2019/2/21
*/
public class InheritThreadLocalTest {
private static final ThreadLocal<String> nameThreadLocal = new InheritableThreadLocal<String>() {
@Override
protected String initialValue() {
return "sunquan";
}
};
public static void main(String[] args) throws InterruptedException {
nameThreadLocal