ThreadLocal是Java并发编程中的常用类,可以解决多个线程共享变量问题,这是不同于“synchronized”的解决方法。
ThreadLocal介绍
ThreadLocal在每个线程中维护一个映射MAP,每个线程都单独有一个变量的副本,实现线程间变量隔离。
在并发编程中,我们可能会遇到多个线程使用同一变量的情境。比如T1,T2,两个线程,T1在操作某对象时T2也同时操作该对象,造成数据混乱,结果与预期不符。对于这种情况常用做法是对操作对象进行同步处理(synchronized),但是同步操作会降低执行效率。ThreadLocal提供了另一种方式来解决并发问题,每个线程都操作同一个变量的副本,不影响其他线程中该变量的值。
ThreadLocal常用方法
ThreadLocal类主要有get(),set(T value),remove(),initialValue()几个方法,结构简单清晰。
- get()方法可以获得该线程所维护的Map表,如果在之前没有使用set(T value)方法设值,则会获得null值,所以建议重写initialValue()方法,自定义默认返回值。
- set(T value)用来设置当前线程中该ThreadLocal对应的值,Key是该ThreadLocal的引用。
- remove()方法用来擦除线程中当前Threadlocal所映射的值。
- initialValue()是定义默认返回值的方法,推荐在使用ThreadLocal时重写该方法,自定义默认返回值。
//创建ThreadLocal时重写initialValue()方法
public class TestThreadLocal {
private static final ThreadLocal<String> value = new ThreadLocal<String>() {
@Override
protected String initialValue() {
return "Djz";
}
};
}
ThreadLocal总结
- 使用ThreadLocal可以在每个线程中保存同一个变量的副本,值相同,但是各线程操作的是自己线程中所保存的副本,不会互相影响,不同于同步操作思路解决了多线程并发问题。
- ThreadLocal类将自己的引用作为Key值,存储对象作为Value,存储在每个线程所维护的Map映射表中,这样设计可以使Map与线程绑定,当线程被销毁后,所维护的Map映射表也会被销毁。
- 在创建ThreadLocal建议重写initialValue()方法,因为该方法默认返回null值,存在NPE隐患。
- 由于ThreadLocal提供了线程内部的局部变量,因此该变量生命周期与线程相同,当线程销毁时该局部变量也会销毁。
- 因为ThreadLocal是在每个线程中都存储一个对象的副本,因此对内存的消耗相比不使用ThreadLocal更大。
- ThreadLocal也解决了变量传递问题,在整个线程内ThreadLocal所映射的对象全局共享,降低了编码时的复杂度。