一、ThreadLocal 介绍
在并发的情况下,多个线程会同时访问同一个变量,这会引起线程安全问题。而ThreadLocal 针对这种情况就被提了出来。他的思想从他的名字就可以看出来,线程局部(变量),即当多个线程访问同一个变量时,每个线程都会拿到这个变量的一个副本,各个线程操作的各自副本,互不干扰。
二、思想的具体实现
Thread类有一个类型为ThreadLocal.ThreadLocalMap的实例变量threadLocals,也就是说每个线程有一个自己的ThreadLocalMap。ThreadLocalMap有自己的独立实现,可以简单地将它的key视作ThreadLocal,value为代码中放入的值(实际上key并不是ThreadLocal本身,而是它的一个弱引用)。每个线程在往某个ThreadLocal里塞值的时候,都会往自己的ThreadLocalMap里存,读也是以某个ThreadLocal作为引用,在自己的map里找对应的key,从而实现了线程隔离。
三、使用案例
package com.dason.first;
import java.util.Random;
public class ThreadLocalDemo {
private static ThreadLocal<Integer> x = new ThreadLocal<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);
x.set(data);
new A().get();
new B().get();
}
}).start();
}
}
static class A{
public void get(){
int data = x.get();
System.out.println("A from " + Thread.currentThread().getName()
+ " get data :" + data);
}
}
static class B{
public void get(){
int data = x.get();
System.out.println("B from " + Thread.currentThread().getName()
+ " get data :" + data);
}
}
}
四、封装
public class ThreadLocalDemo {
public static void main(String[] args) {
for(int i=0;i<2;i++){
new Thread(new Runnable(){
@Override
public void run() {
ThreadLocalValue.getInstance()
.setName(Thread.currentThread().getName());
new A().get();
new B().get();
}
}).start();
}
}
static class A{
public void get(){
ThreadLocalValue myData = ThreadLocalValue.getInstance();
System.out.println("A from " + Thread.currentThread().getName()
+ " getMyData: " + myData.getName());
}
}
static class B{
public void get(){
ThreadLocalValue myData = ThreadLocalValue.getInstance();
System.out.println("B from " + Thread.currentThread().getName()
+ " getMyData: " + myData.getName());
}
}
}
class ThreadLocalValue{
private ThreadLocalValue(){}
public static ThreadLocalValue getInstance(){
ThreadLocalValue instance = map.get();
if(instance == null){
instance = new ThreadLocalValue();
map.set(instance);
}
return instance;
}
private static ThreadLocal<ThreadLocalValue> map = new ThreadLocal<ThreadLocalValue>();
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
五、源码解析
待续。。。