标签:原理 ret runnable 图片 工具 returns 映射 成员 tar
ThreadLocal是什么
ThreadLocal是一个本地线程副本变量工具类。主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别适用于各个线程依赖不通的变量值完成操作的场景。
下图为ThreadLocal的内部结构图
从上面的结构图,我们已经窥见ThreadLocal的核心机制:
Thread线程内部的Map在类中描述如下:
public class Thread implements Runnable {
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
}
ThreadLocal类提供如下几个核心方法:
public T get()
public void set(T value)
public void remove()
protected T initialValue()
get()方法
/**
* Returns the value in the current thread‘s copy of this
* thread-local variable. If the variable has no value for the
* current thread, it is first initialized to the value returned
* by an invocation of the {@link #initialValue} method.
*
* @return the current thread‘s value of this thread-local
*/
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}
protected T initialValue() {
return null;
}
步骤:
set()方法
/**
* Sets the current thread‘s copy of this thread-local variable
* to the specified value. Most subclasses will have no need to
* override this method, relying solely on the {@link #initialValue}
* method to set the values of thread-locals.
*
* @param value the value to be stored in the current thread‘s copy of
* this thread-local.
*/
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 getMap(Thread t) {
return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
步骤:
remove()方法
/**
* Removes the current thread‘s value for this thread-local
* variable. If this thread-local variable is subsequently
* {@linkplain #get read} by the current thread, its value will be
* reinitialized by invoking its {@link #initialValue} method,
* unless its value is {@linkplain #set set} by the current thread
* in the interim. This may result in multiple invocations of the
* <tt>initialValue</tt> method in the current thread.
*
* @since 1.5
*/
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
举个例子
public class Demo {
private ThreadLocal<Integer> counts = new ThreadLocal<Integer>(){
protected Integer initialValue() {
return 0;
}
};
public void set(Integer value){
counts.set(value);
}
public Integer getNext(){
Integer integer = counts.get();
integer++;
counts.set(integer);
return integer;
}
public static void main(String[] args) {
new Thread(new Runnable() {
Demo d = new Demo();
@Override
public void run() {
while(true){
Integer next = d.getNext();
System.out.println(Thread.currentThread().getName()+" : "+next);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
Demo d = new Demo();
@Override
public void run() {
while(true){
Integer next = d.getNext();
System.out.println(Thread.currentThread().getName()+" : "+next);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
运行结果:
看以看出来ThreadLocal是线程安全的
最常见的ThreadLocal使用场景为 用来解决 数据库连接、Session管理等。
标签:原理 ret runnable 图片 工具 returns 映射 成员 tar
原文地址:https://www.cnblogs.com/jacky804828002/p/ThreadLocal-de-shi-yong-he-yuan.html