线程范围内的共享变量,通俗的说就是指:特定的线程对应特定的数据,不会因为对象的变化数据而改变。
ThreadLocal 的使用方便我们对不同的线程管理不同的数据,而且能够很好的对单例进行复用,因为我们通常不同的数据对象对应不同的单例进行保存,如果一旦分类数据过多,那么我们得创建大量的单例进行保存。然而ThreaLocal能够做到单例的复用。下面请看代码
public class ThreadScopShareData {
static ThreadLocal<Integer> x= new ThreadLocal<Integer>();
// private static int data = 0;
// private static Map<Thread,Integer> threadData = new HashMap<Thread, Integer>();//此处为了相同的线程能够拿到共同的数据
public static void main(String[] args) {
for(int i = 0;i<2;i++){
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
int data = new Random().nextInt();
System.out.println(Thread.currentThread().getName()+"has put data: "+data);
x.set(data);//数据存入到当前线程中
// threadData.put(Thread.currentThread(),data);
MyThreadScopeData.getInstance().setName("name"+data);//本线程对应的实例
MyThreadScopeData.getInstance().setAge(data);
new A().get();
new B().get();
}
}).start();
}
}
static class A{
public int get(){
// int data = threadData.get(Thread.currentThread());
int data = x.get();//获取当前线程数据
System.out.println("A from"+Thread.currentThread().getName()+"get data: "+data);
MyThreadScopeData mydata = MyThreadScopeData.getInstance();
System.out.println("A from"+Thread.currentThread().getName()+"get Mydata: "+mydata.getAge()+","+mydata.getName());
return data;
}
}
static class B{
public int get(){
int data = x.get();//获取当前线程数据
// int data = threadData.get(Thread.currentThread());
System.out.println("B from"+Thread.currentThread().getName()+"get data: "+data);
MyThreadScopeData mydata = MyThreadScopeData.getInstance();
System.out.println("B from"+Thread.currentThread().getName()+"get Mydata: "+mydata.getAge()+","+mydata.getName());
return data;
}
}
}
class MyThreadScopeData{
// private static MyThreadScopeData instance=null;
private MyThreadScopeData(){
}
public static /*synchronized*/ MyThreadScopeData getInstance(){//加同步锁是为了防止出现多个对象
MyThreadScopeData instance = map.get();//此处可以针对不同线程new 对应的单例,提高代码的复用
if(instance ==null){
instance = new MyThreadScopeData();
map.set(instance);
}
return instance;
}
private static ThreadLocal<MyThreadScopeData> map = new ThreadLocal<MyThreadScopeData>();
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
该代码的运行结果为
可见对象的不同,只要是线程一样数据就一样。
这对于我们在处理并发访问上给出了一些提示。