借鉴:百度安全验证
前言:
当多线程访问共享可变数据时,涉及到线程间同步的问题,并不是所有时候,都要用到共享数据,所以就需要线程封闭出场了。
数据都被封闭在各自的线程之中,就不需要同步,这种通过将数据封闭在线程中而避免使用同步的技术称为线程封闭。
本文主要介绍线程封闭中的其中一种体现:ThreadLocal,将会介绍什么是 ThreadLocal;从 ThreadLocal 源码角度分析,最后介绍 ThreadLocal 的应用场景。
什么是 ThreadLocal?
ThreadLocal 是 Java 里一种特殊变量,它是一个线程级别变量,每个线程都有一个 ThreadLocal 就是每个线程都拥有了自己独立的一个变量,竞态条件被彻底消除了,在并发模式下是绝对安全的变量。
可以通过 ThreadLocal<T> value = new ThreadLocal<T>() 来使用。
会自动在每一个线程上创建一个 T 的副本,副本之间彼此独立,互不影响,可以用 ThreadLocal 存储一些参数,以便在线程中多个方法中使用,用以代替方法传参的做法。
下面通过例子来了解下 ThreadLocal:
public class ThreadLocalDemo {
public static final ThreadLocal<String> THREAD_LOCAL = new ThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
new ThreadLocalDemo().threadTest();
}
private void threadTest() throws InterruptedException {
THREAD_LOCAL.set("main");
String resultStart = THREAD_LOCAL.get();
System.out.println("Thread-0执行之前:" +
Thread.currentThread().getName() + " threadLocal:" + resultStart);
new Thread(new Runnable() {
@Override
public void run() {
String resultIng1 = THREAD_LOCAL.get();
System.out.println(Thread.currentThread().getName() + " threadLocal:" + resultIng1);
THREAD_LOCAL.set("test02");
String resultIng2 = THREAD_LOCAL.get();
System.out.println("Thread-0重新设置之后:" +
Thread.currentThread().getName() + " threadLocal:" + resultIng2);
}
}
).start();
Thread.sleep(3000);
String resultEnd = THREAD_LOCAL.get();
System.out.println("Thread-0执行之后:" +
Thread.currentThread().getName() + " threadLocal:" + resultEnd);
}
}
结果
Thread-0执行之前:main threadLocal:main
Thread-0 threadLocal:null
Thread-0重新设置之后:Thread-0 threadLocal:test02
Thread-0执行之后:main threadLocal:main
结论:
这个变量在不同线程中取到的值是不同的,不同线程之间对于 ThreadLocal 会有对应的副本,这就是线程的封闭
使用场景:
用户登录的时候将用户信息保存到缓存中,每次解析token,然后一层一层的传递?这样会不会导致代码太过耦合呢?使用ThreadLocal在登录拦截器中在当前线程中保存用户信息,这样就可以直接从全局的ThreadLocal中很方便的获取用户信息。