本文内容部分引自《Java多线程编程核心技术》,感谢作者!!!
代码地址:https://github.com/xianzhixianzhixian/thread.git
ThreadLocal和InheritableThreadLocal基本用法
1、ThreadLocal和InheritableThreadLocal都是为了解决每个线程绑定自己的值,其中可以存放每个线程的私有数据,存放的数据在不同线程之间具有隔离性。
2、使用ThreadLocal和InheritableThreadLocal类中的get()方法来获取值,set()方法来设置线程自己的私有数据。
3、ThreadLocal和InheritableThreadLocal类中的get()方法第一次返回值为null,可以自己写一个拓展类Ext,重写其中的initialValue()方法来改变第一次使用get()函数时的返回值。
4、ThreadLocal和InheritableThreadLocal的不同:使用InheritableThreadLocal类时可以在子线程中获得父线程继承下来的值;使用InheritableThreadLocal时,子线程在取值时,如果父线程改变了InheritableThreadLocal中的值,子线程依然取到的是旧值。
ThreadLocal简单用法以及解决第一次get为null的情况
ThreadLocalExt.java
/**
* 解决第一次get()返回null的问题
* @author: xianzhixianzhixian
* @date: 2019-01-08 20:18
*/
public class ThreadLocalExt extends ThreadLocal {
@Override
protected Object initialValue() {
return "我是默认值,第一次get不再为null";
}
}
Run.java
/**
* 解决第一次get()返回null的问题,这里是针对main线程的
* @author: xianzhixianzhixian
* @date: 2019-01-08 20:19
*/
public class Run {
public 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());
}
}
运行结果:第一次get获得的值为字符串"我是默认值,第一次get不再为null",可见成功
InheritableThreadLocal简单使用以及基本用法第4点验证
InheritableThreadLocal.java
/**
* InheritableThreadLocal类可以让子线程从父类线程中取得值
* 子线程在取值时,如果父线程改变了InheritableThreadLocal中的值,子线程依然取到的是旧值
* @author: xianzhixianzhixian
* @date: 2019-01-08 20:39
*/
public class InheritableThreadLocalExt extends InheritableThreadLocal {
@Override
protected Object initialValue() {
return new Date().getTime();
}
@Override
protected Object childValue(Object parentValue) {
return parentValue+"我在子线程加的~!";
}
}
Tools.java
/**
* @author: xianzhixianzhixian
* @date: 2019-01-08 20:42
*/
public class Tools {
public static InheritableThreadLocalExt t1 = new InheritableThreadLocalExt();
}
ThreadA.java
/**
* @author: xianzhixianzhixian
* @date: 2019-01-08 20:45
*/
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) {
e.printStackTrace();
}
}
}
Run.java
/**
* @author: xianzhixianzhixian
* @date: 2019-01-08 20:50
*/
public class Run {
public static void main(String[] args) {
try {
for (int i = 0; i < 10; i++) {
System.out.println("在Main线程中取值="+Tools.t1.get());
Thread.sleep(100);
}
Thread.sleep(5000);
ThreadA a = new ThreadA(); //InheritableThreadLocal类可以让子线程从父类线程中取得值,在这里a是子线程
a.start();
Tools.t1.set("Hello world!"); //这里main线程和子线程是同步运行的,main线程在改变值的同时子线程取得的值还是旧值
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:如基本用法中第4点所说