ThreadLock
ThreadLock为每一个线程提供一个局部变量,这个局部变量只有当前线程才可以使用,是线程安全的。
其原理是为每一个线程分配一个对象,这是应用层面来保证的
首先获取到每个线程独有的ThreadLocalMap,然后将ThreadLocal<String> var=new ThreadLocal<>();
中的var当作键,并存放value。
所以Thread只是起到了一个容器的作用,通过ThreadLock的set()跟 get()方法来使用
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
具体Demo
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
// write your code here
Student s=new Student();
Person p=new Person();
new Thread(new Runnable() {
@Override
public void run() {
s.setName("小李小李");
s.setAge(18);
p.setName("小李小李");
p.setAge(18);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(p.toString());
System.out.println(s.toString());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
p.setName("小明");
p.setAge(21);
s.setName("小明");
s.setAge(21);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(p.toString());
System.out.println(s.toString());
}
}).start();
}
}
class Student{
int age;
String name;
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
class Person{
ThreadLocal<String> name=new ThreadLocal<>();
ThreadLocal<Integer> age=new ThreadLocal<>();
public void setName(String name) {
this.name.set(name);
}
public void setAge(int age) {
this.age.set(age);
}
public String getName() {
return this.name.get();
}
public Integer getAge() {
return this.age.get();
}
@Override
public String toString() {
return "Person{" +
"name=" + this.getName() +
", age=" + this.getAge() +
'}';
}
}
输出结果分析
首先定义了两个类Person和Student,其中Student中的对象是用传统的方法,多个线程在对用一个对象进行赋值时会发生覆盖现象
而Person对象采用 ThreadLocal<String>
,每个线程缓冲在自己的ThreadLocalMap中,并不会冲突。