一、ThreadLocal 的使用
ThreadLocal 主要解决的就是每个线程绑定自己的值,可以将ThreadLocal 类比喻成全局存放数据的盒子,盒子中可以存储每个线程的私有数据。
1.ThreadLocal 的初始化
如果不进行初始化第一次调用get()方法时返回的值是null。初始化的方法是 继承ThreadLocal 类 然后重写 initialValue()方法。
重写initialValue()方法:
public class ThreadLocalExt extends ThreadLocal{
@Override
protected Object initialValue() {
return "我是默认值";
}
}
测试代码:
public class Run {
static ThreadLocalExt t1 = new ThreadLocalExt();
public static void main(String[] args){
if(t1.get() == null){
System.out.println("我还没值");
t1.set("放个值");
}
System.out.println(t1.get());
System.out.println(t1.get());
}
}
运行结果:
2.验证线程变量的隔离性
初始化代码:
import java.util.Date;
public class ThreadLocalExt extends ThreadLocal{
@Override
protected Object initialValue() {
return new Date().getTime();
}
}
工具类:
public class Tools {
public static ThreadLocalExt t1 = new ThreadLocalExt();
}
线程代码:
public class ThreadA extends Thread{
@Override
public void run() {
try {
for (int i = 0; i <10; i++){
System.out.println("在ThreadA线程中取值 = " + Tools.t1.get());
Thread.sleep(100);
}
} catch (Exception e) {
}
}
}
测试代码:
public class DemoRun {
public static void main(String[] args) {
try {
for (int i = 0; i<10;i++){
System.out.println("在Main线程中取值 =" + Tools.t1.get());
}
Thread.sleep(4000);
ThreadA a = new ThreadA();
a.start();
} catch (Exception e) {
}
}
}
运行结果:(子线程与主线程各自拥有各自的值)
二、InheritableThreadLocal的使用
使用类InheritableThreadLocal 可以在子线程中取得父线程(主线程)继承下来的值
1.值继承
工具类的代码:
public class Tools {
public static InheritableThreadLocal t1 = new InheritableThreadLocal();
}
线程代码:
public class ThreadA extends Thread{
@Override
public void run() {
for(int i = 0; i < 10; i++){
System.out.println("ThreadA中"+Tools.t1.get());
}
}
}
入口方法:
public class Run {
public static void main(String[] args){
try {
Tools.t1.set(22222);
System.out.println("main中"+Tools.t1.get());
Thread.sleep(1000);
ThreadA a = new ThreadA();
a.start();
} catch (InterruptedException e) {
}
}
}
运行结果:(子线程中取得了主线程的值)
2.值继承再修改
重写InheritableThreadLocal 类中的childValue()方法。
重写childValue()方法:
public class InheritableThreadLocalExt extends InheritableThreadLocal<Object>{
@Override
protected Object childValue(Object parentValue) {
return parentValue + "这是怎么回事呢";
}
}
更改工具类:
public class Tools {
public static InheritableThreadLocalExt t1 = new InheritableThreadLocalExt();
}
运行结果:
注意:如果子线程在取值的同时,主线程将InheritableThreadLocal 中的值进行更改,那么子线程取得的值还是旧值。
验证:更改入口方法
public class Run {
public static void main(String[] args){
try {
Tools.t1.set(22222);
System.out.println("main中"+Tools.t1.get());
Thread.sleep(1000);
ThreadA a = new ThreadA();
a.start();
Tools.t1.set(3333);
System.out.println("main2中"+Tools.t1.get());
} catch (InterruptedException e) {
}
}
}
运行结果: