其他理解:
不应该只把它当作一个传参工具,它本身是为线程安全和某些特定场景的问题而设计的。
诡异的ThreadLocal最难琢磨的是“
作用域”,尤其是在代码设计之初非常乱的情况下,假设再添加很多ThreadLocal。系统就会逐渐变成神龙见首不见尾的情况。
使用ThreadLocal,不要简单粗暴地多一个參数就加一个ThreadLocal变量。比如,我们能够设计几种对象来封装入口參数,在接口设计时入口參数都以对象为基础。
使用ThreadLocal,不要简单粗暴地多一个參数就加一个ThreadLocal变量。比如,我们能够设计几种对象来封装入口參数,在接口设计时入口參数都以对象为基础。
通过一个简单示例解释怎么应用ThreadLocal:
public class Deomo01 {
public static void main(String p[]) {
ThreadLocalString tStringA = new ThreadLocalString("线程A");
ThreadLocalString tStringB = new ThreadLocalString("线程B");
ThreadLocalString tStringC = new ThreadLocalString("线程C");
tStringA.start();
tStringB.start();
tStringC.start();
}
public static class ThreadLocalString extends Thread{
//线程名称
private String name ;
public ThreadLocalString () {};
public ThreadLocalString(String name) {
this.name = name;
}
@Override
public void run() {
for(int i = 0 ; i < 10 ; i++) {
if(ThreadLocalManager.get() == null) {
ThreadLocalManager.set(String.valueOf(0));
System.out.println(name+"-->"+ThreadLocalManager.get());
}else {
String str = ThreadLocalManager.get();
ThreadLocalManager.set(String.valueOf(Integer.parseInt(str)+1));
System.out.println(name+"-->"+ThreadLocalManager.get());
if(i==6) {
ThreadLocalManager.remove();
System.out.println("将当前这个线程的ThreadLocal清除后:"+ThreadLocalManager.get());
}
}
}
}
}
}
public class ThreadLocalManager {
private static ThreadLocal<String> myThreadLocal = new ThreadLocal<String>();
public static String get() {
return myThreadLocal.get();
}
public static void set(String i) {
myThreadLocal.set(i);
}
public static void remove() {
myThreadLocal.remove();
}
}
内在原理解释:
ThreadLocal最常见的操作就是set、get、remove三个动作。以下来看看这三个动作究竟做了什么事情:
代码中有两条路径须要追踪,各自是getMap(Thread)和createMap(Thread , T)。首先来看看
getMap(t)操作:
这个ThreadLocalMap是ThreadLocal里面的内部类。放在了Thread类里面作为一个私有变量而存在,所以是线程安全的。ThreadLocal本身成为这个Map里面存放的Key,用户输入的值是Value。
代码逻辑:
1.ThreadLocal通过Thread.currentThread()获取当前的线程就能得到这个Map对象。
2.同一时候将自身作为Key发起写入和读取,因为将自身作为Key,所以一个ThreadLocal对象就能存放一个线程中相应的Java对象。通过get也自然能找到这个对象。
再来看看
createMap:
将第一个值作为这个Map的初始化值,因为这个Map是线程私有的。不可能有还有一个线程同一时候也在对它做put操作,因此这里的赋值和初始化是绝对线程安全的,也同一时候保证了每个外部写入的值都将写入到Map对象中。
get和remove方法:
ThreadLocal的应用场景举例: