1,ThreadLocal类主要解决的是每个线程绑定自己的值,这里存储的是每个线程私有的数据,解决了变量在不同线程间的隔离性。
测试代码:
public class Tools {
public static ThreadLocal tl = new ThreadLocal();
}
public class ThreadA extends Thread {
@Override
public void run() {
try {
for(int i=0; i<10; i++){
Tools.tl.set("ThreadA "+(i+1));
System.out.println("ThreadA get value="+Tools.tl.get());
}
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadB extends Thread {
@Override
public void run() {
try {
for(int i=0; i<10; i++){
Tools.tl.set("ThreadB "+(i+1));
System.out.println("ThreadB get value="+Tools.tl.get());
}
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class RunTest {
public static void main(String[] args) {
ThreadA ta = new ThreadA();
ThreadB tb = new ThreadB();
ta.start();
tb.start();
}
}
运行结果:
ThreadB get value=ThreadB 1
ThreadA get value=ThreadA 1
ThreadA get value=ThreadA 2
ThreadA get value=ThreadA 3
ThreadA get value=ThreadA 4
ThreadA get value=ThreadA 5
ThreadA get value=ThreadA 6
ThreadA get value=ThreadA 7
ThreadA get value=ThreadA 8
ThreadA get value=ThreadA 9
ThreadA get value=ThreadA 10
ThreadB get value=ThreadB 2
ThreadB get value=ThreadB 3
ThreadB get value=ThreadB 4
ThreadB get value=ThreadB 5
ThreadB get value=ThreadB 6
ThreadB get value=ThreadB 7
ThreadB get value=ThreadB 8
ThreadB get value=ThreadB 9
ThreadB get value=ThreadB 10
每个线程都取出了自己设置的值。
2,ThreadLocal第一次get会返回null,可以通过重载其方法initialValue来设置默认值。
测试代码:
public class Tools {
public static ThreadLocalExt tl = new ThreadLocalExt();
}
class ThreadLocalExt extends ThreadLocal{
@Override
protected Object initialValue() {
System.out.println("default value not null.");
return new Date().getTime();
}
}
public class ThreadA extends Thread {
@Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("ThreadA get value="+Tools.tl.get());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadB extends Thread {
@Override
public void run() {
try {
Thread.sleep(8000);
System.out.println("ThreadB get value="+Tools.tl.get());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class RunTest {
public static void main(String[] args) {
ThreadA ta = new ThreadA();
ThreadB tb = new ThreadB();
ta.start();
tb.start();
if(Tools.tl.get() == null){
System.out.println("main thread 还没有设置过值");
Tools.tl.set(new Date().getTime());
}
System.out.println("main thread ,tl="+Tools.tl.get());
}
}
运行结果:
default value not null.
main thread ,tl=1516241174168
default value not null.
ThreadA get value=1516241176167
default value not null.
ThreadB get value=1516241182168
每个线程都有自己的初始值。
3,InheritableThreadLocal的使用
类InheritableThreadLocal,可以让子线程取得从父线程继承下来的。
测试代码:
public class Tools {
public static InheritableThreadLocalExt tl = new InheritableThreadLocalExt();
}
class InheritableThreadLocalExt extends InheritableThreadLocal{
@Override
protected Object initialValue() {
System.out.println("default value not null.");
return new Date().getTime();
}
@Override
protected Object childValue(Object parentValue) {
System.out.println("child value inheritable.");
return parentValue+"-child change value";
}
}
public class RunTest {
public static void main(String[] args) {
if(Tools.tl.get() == null){
System.out.println("main thread 还没有设置过值");
Tools.tl.set(new Date().getTime());
}
System.out.println("main thread ,tl="+Tools.tl.get());
ThreadA ta = new ThreadA();
ThreadB tb = new ThreadB();
ta.start();
tb.start();
}
}
ThreadA,ThreadB的代码不变,但是RunTest.java代码稍微有改动,就是把ThreadA,ThreadB的对象创建放在了主线程的这句:System.out.println("main thread ,tl="+Tools.tl.get());之后。如果把线程A,B的创建放在这句调用之前,A,B线程不会继承父线程(主线程)的值。
protected Object childValue(Object parentValue) {}是在继承的同时,可以对值做修改。
运行结果:
default value not null.
main thread ,tl=1516245837214
child value inheritable.
child value inheritable.
ThreadA get value=1516245837214-child change value
ThreadB get value=1516245837214-child change value
可以看到,虽然线程A,B都有几秒的延迟,但是获取的时间都是main线程的InheritableThreadLocal的时间。