其他理解:
不应该只把它当作一个传参工具,它本身是为线程安全和某些特定场景的问题而设计的。
诡异的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的应用场景举例: