前言:
对于多线程来说,我记住最多的一句就是线程操作资源类,在资源类中变量的值的共享可以使用public static变量的形式,所有的线程都使用同一个public static 变量。线程都可以对此变量进行操作更改。但是如果想实现每一个线程都有自己的共享的变量该如何解决,于是ThreadLocal出现,解决了此问题。
1 理解ThreadLocal
类ThreadLocal主要解决的就是每个线程绑定自己的值,可以将ThreadLocal类比喻成全局存放数据的盒子,盒子中可以存储 每个线程的私有数据
2 代码
线程A:
public class ThreadA extends Thread {
@Override
public void run(){
try {
for (int i = 0; i <100 ; i++) {
Tools.t1.set("ThreadA"+(i+1));
System.out.println("ThreadA get Value="+Tools.t1.get());
Thread.sleep(200);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
线程B:
public class ThreadB extends Thread {
@Override
public void run(){
try {
for (int i = 0; i <100 ; i++) {
Tools.t1.set("ThreadB"+(i+1));
System.out.println("ThreadB get Value="+Tools.t1.get());
Thread.sleep(200);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
资源类:
public class Tools {
public static ThreadLocal t1=new ThreadLocal();
}
主线程:
public class Main {
public static void main(String[] args) {
try{
ThreadA a =new ThreadA();
ThreadB b=new ThreadB();
a.start();
b.start();
for (int i = 0; i <100 ; i++) {
Tools.t1.set("Main"+(i+1));
System.out.println("Main get Value="+Tools.t1.get());
Thread.sleep(200);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
结果:
线程A、线程B以及主线程都向中set值,但是每个线程取出的都是自己线程的值,说明线程变量ThreadLocal具有隔离性
3、解决get()是null问题
重写initialValue 写出返回你想要的初始值就好
public class ThreadLocalExt extends ThreadLocal {
@Override
protected Object initialValue(){
return "";
}
}
4、类InheritableThreadLocal的使用
可以在子线程中取得父线程继承下来的值,java中父线程只是一种逻辑称呼,创建线程的当前线程就是新线程的父线程
eg:
public class InheritablethreadLocalExt extends InheritableThreadLocal {
@Override
protected Object initialValue() {
return new Date().getTime();
}
@Override
protected Object childValue(Object parentValue){
return parentValue+"我在子线程加的";
}
}
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 (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Tools {
public static InheritablethreadLocalExt t1=new InheritablethreadLocalExt();
}
public class Main {
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();
a.start();
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
结果:
以上代码需要注意:
如果子线程在取得值的同时,主线程将InheritableThreadLocal的值进行更改,那么子线程取得的值还是旧值。