什么是线程范围内共享变量?
线程范围内的共享变量是指对同一个变量,几个线程同时对它进行写和读操作,而同一个线程读到的数据就是它自己写进去的数据。也就是说每个线程只能访问他自己的,不能访问别的线程的。
首先我们看未实现范围内共享变量的例子,以此来解决线程范围内共享变量的解决方式:
public class ThreadScopeShareData {
private static int data = 0;
public static void main(String[] args) {
//启动两个线程
for(int i=0;i<2;i++){
new Thread(new Runnable(){
@Override
public void run() {
data = new Random().nextInt();
System.out.println(Thread.currentThread().getName()
+ " has put data :" + data);
new A().get();
new B().get();
}
}).start();
}
}
static class A{
public void get(){
System.out.println("A from " + Thread.currentThread().getName()
+ " get data :" + data);
}
}
static class B{
public void get(){
System.out.println("B from " + Thread.currentThread().getName()
+ " get data :" + data);
}
}
}
输出结果:
Thread-0 has put data :533593121
Thread-1 has put data :343058745
A from Thread-0 get data :343058745
A from Thread-1 get data :343058745
B from Thread-1 get data :343058745
B from Thread-0 get data :343058745
对于这种情况可以采用以下方法实现:
1.将写的数据放入一个Map的value中,key就是进行这个写操作的线程对象,这样读的时候每个线程就只能从Map中读到自己对应的value。
2.使用ThreadLocal,ThreadLocal类似Map,它可以为每个线程装载一个对象,这个对象是和线程绑定的,ThreadLocal在哪个线程中执行操作,它就会自动选择那个与线程绑定的对象。
下面我们看通过Map的方式如何实现:
public class ThreadScopeShareData {
//private static int data = 0;
//将写的数据放入Map的value中,key就是进行这个写操作的线程对象
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() {
int data = new Random().nextInt();
System.out.println(Thread.currentThread().getName()
+ " has put data :" + data);
//设置当前线程key和value
threadData.put(Thread.currentThread(), data);
new A().get();
new B().get();
}
}).start();
}
}
static class A{
public void get(){
//取出map中当前线程key对应的value
int data = threadData.get(Thread.currentThread());
System.out.println("A from " + Thread.currentThread().getName()
+ " get data :" + data);
}
}
static class B{
public void get(){
//取出map中当前线程key对应的value
int data = threadData.get(Thread.currentThread());
System.out.println("B from " + Thread.currentThread().getName()
+ " get data :" + data);
}
}
}
Thread-0 has put data :-1979727275
Thread-1 has put data :1534341934
A from Thread-1 get data :1534341934
A from Thread-0 get data :-1979727275
B from Thread-1 get data :1534341934
B from Thread-0 get data :-1979727275
我们通过Map的key/value形式,区分了线程及其数据,以实现了线程范围内的共享变量。
线程范围内共享变量的用处:
例如我们上面的实例中,在线程范围内需要多个模块完成,而不影响其他线程,也就是数据要在线程内共享,线程外独立。
后文我们将继续使用ThreadLocal来解决线程范围内共享变量问题,以及对ThreadLocal的更多认识。