一、 ThreadLocal的使用
-
正常的情况下,person对象是这两个线程共有的,即使用同一个对象,因此当一个线程修改person的name时,另一个线程的name也会改变。
public class ThreadLocal1 {
static class Person {
String name = "zhangsan";
}
volatile static Person p = new Person();
public static void main(String[] args) {
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(p.name);
}).start();
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
p.name = "lisi";
}).start();
}
}
-
若使用ThreadLocal,则每一个线程都具有其独有的person对象,相互两个线程之间不影响
-
ThreadLocal的用途:声明式事务,保证同一个Connection
public class ThreadLocal2 {
//volatile static Person p = new Person();
static ThreadLocal<Person> tl = new ThreadLocal<>();
public static void main(String[] args) {
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(tl.get());
}).start();
new Thread(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
tl.set(new Person());
}).start();
}
static class Person {
String name = "zhangsan";
}
}
二、 源码分析
- set
- Thread.currentThread().ThreadLocalMap(ThreadLocal,value)
- 设到了当前线程的ThreadLocalMap中
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
map.set(this, value);
} else {
createMap(t, value);
}
}
- 弱引用
ThreadLocalMap里的Entry继承于WeakReference,因此Entry里保存的ThreadLocal引用是弱引用
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
Comments | 0 条评论