1、什么叫线程范围的数据共享
在Java线程中,有的时候需要使用多个线程,并且多个线程之间数据独立,但在每个线程内部是数据共享的,如下图中有n个线程thread,但是每个thread只操作自己对应的数据(这就叫线程范围内数据共享),不会操作其他线程所对应的数据(这叫线程外数据独立)。比如实际列子中到银行取钱,张三给李四存钱,王五取钱,相当于两个线程操作两组数据,张三的钱不能转到王五的账号上,王五取的钱不能是李四账号上的钱。这就是线程范围内的数据共享。
thread1 | data1 |
thread2 | data2 |
…… | |
threadn | datan |
2、如何实现线程范围内数据
可以将各自的数据与线程对应起来,用map存储,用对应的线程为key,以每个线程内的数据为value即可,demo如下:
public class Demo{
private static final Map<Thread,Integer> threadData = new HashMap<Thread,Integer>();
public static void main(){
for(int i=0;i<2;i++){
new Thread(new Runnable(){
@Override
onRun(){
int data=new Random().nextInt();
threadMap.put(Thread.currentThread,data);
new A().get();
new B().get();
}
}).start();
}
}
public static class A{
public void get(){
data = threadMap.get(Thread.currentThread);
System.out.println("A "+Thread.currentThread.getName()+" data:"+data);
}
}
public static class B{
public void get(){
data = threadMap.get(Thread.currentThread);
System.out.println("B "+Thread.currentThread.getName()+" data:"+data);
}
}
}
3、ThreadLocal类
Java 提供了类似与2中提到的map功能,做到线程内数据共享,线程外独立:ThreadLocal类。ThreadLocal类的原理其实就是内部用的就是map,key是当前线程,value是T(泛型),demo2如下:
public class Demo2{
private static final ThreadLocal<Integer> threadData = new ThreadLocal<Integer>();
public static void main(){
for(int i=0;i<2;i++){
new Thread(new Runnable(){
int data=new Random().nextInt();
threadData.set(data);//存储,默认key就是当前线程
new A().get();
new B().get();
}).start();
}
}
public static class A{
public void get(){
int data = threadData.get();//取数据,默认key就是当前线程
System.out.println("A "+Thread.currentThread.getName()+" data:"+data);
}
}
public static class B{
public void get(){
int data = threadData.get();//取数据,默认key就是当前线程
System.out.println("B "+Thread.currentThread.getName()+" data:"+data);
}
}
}
注意:ThreadLocal类只能放一种泛型的数据,如果有多种数据类型的数据需要线程内数据共享,那么就需要数据打包即可。其次当不需要ThreadLocal类所保存的数据时候,可以调用clear方法释放内存。其次如果不调用ThreadLocal的clear方法释放内存,当线程结束后,会自动的释放对应线程中的数据,达到释放内存的效果。