1.ThreadLocal干什么的?
ThreadLocal是用来做线程内部变量传递的,绝非线程间通信或线程同步的!
2. ThreadLocal工作原理
是每个Java线程拥有一个ThreadLocal.ThreadLocalMap的成员变量,这个map的key就是ThreadLocal对象,value就是当前线程的目标变量的包装类Entry。而绝非ThreadLocal为每个thread保存变量,这很重要。
所以当线程消亡的时候,其相关的threadLocal的变量自然就被GC了。
3. ThreadLocal保存变量的生命周期是怎么样的?
ThreadLocal保存变量的生命周期 <=任务的生命周期<=线程的生命周期
使用ThreadLocal过程: 对于每一个需要线程保存自身实例的变量,需要定义一个静态的ThreadLocal实例。然后将一个共用的ThreadLocal静态实例作为key,将 不同对象的引用保存到不同线程的ThreadLocalMap中,然后在线程执行的各处通过这个静态ThreadLocal实例的get()方法取得自己 线程保存的那个对象。
4. ThreadLocal的应用及源代码解析
- public class UserContextHolder {
- private static final ThreadLocal<User> userThreadLocal = new ThreadLocal<User>();
- public static User get(){
- return userThreadLocal.get();
- }
- public static void set(User user){
- userThreadLocal.set(user);
- }
- }
UserContextHolder的get方法最终会调用ThreadLocal的get方法,ThreadLocal的get方法如下:
- public T get() {
- Thread t = Thread.currentThread();//取得当前的thread
- ThreadLocalMap map = getMap(t);//取得当前thread的ThreadLocalMap对象
- if (map != null) { //返回key为当前ThreadLocal的value值
- ThreadLocalMap.Entry e = map.getEntry(this);
- if (e != null)
- return (T)e.value;
- }
- return setInitialValue();//返回默认值null
- }
ThreadLocalMap 的key为当前的Threadlocal对象,Threadlocal对象的hashcode实现如下:
- private final int threadLocalHashCode = nextHashCode();
- private static AtomicInteger nextHashCode = new AtomicInteger();
- private static final int HASH_INCREMENT = 0x61c88647;
- private static int nextHashCode() {
- return nextHashCode.getAndAdd(HASH_INCREMENT);
- }
Threadlocal对象的hashcode值是递增的,是HASH_INCREMENT的N倍.这个也和以前遇到的hashcode的生成方式不一样
UserContextHolder的set方法最终会调用ThreadLocal的set方法,ThreadLocal的set方法如下:
- public void set(T value) {
- Thread t = Thread.currentThread();
- ThreadLocalMap map = getMap(t);//取得当前线程对应的ThreadLocalMap
- if (map != null) //ThreadLocalMap不空,把value以当前ThreadLocal为key放到ThreadLocalMap 中
- map.set(this, value);
- else //创建一个ThreadLocalMap.并把value放到ThreadLocalMap中
- createMap(t, value);
- }
ThreadLocal还有一个常用的方法remove,如下:
- public void remove() {
- ThreadLocalMap m = getMap(Thread.currentThread());
- if (m != null)
- m.remove(this);
- }
- /**
- * Remove the entry for key.
- */
- private void remove(ThreadLocal key) {
- Entry[] tab = table;
- int len = tab.length;
- int i = key.threadLocalHashCode & (len-1);
- for (Entry e = tab[i];
- e != null;
- e = tab[i = nextIndex(i, len)]) {
- if (e.get() == key) {
- e.clear();
- expungeStaleEntry(i);
- return;
- }
- }
- }
5.ThreadLocal的set(null)和remove方法有什么区别?
set(null)把当前的ThreadLocal为key的值设为了空,避免线程下次再执行其他任务时被使用,但此时这个key对应的Entry值还在,只是Entry.value=null
remove方法会把这个key对应Entry的值设为空
所以从重用和效率的角度来说,set(null)的性能优于remove,在实际的项目中推荐使用set(null)来回收ThreadLocal设置的值.
6. 为什么ThreadLocalMap的Entry是一个weakReference?
使用weakReference,能够在ThreadLocal失去强引用的时候,ThreadLocal对应的Entry能够在下次gc时被回收,回收后的空间能够得到复用,在一定程度下能够避免内存泄露.
7.使用ThreadLocal应该注意什么?
在使用ThreadLocal对象,尽量使用static,不然会使线程的ThreadLocalMap产生太多Entry,从而造成内存泄露
相关推荐
ThreadLocal 详解 ThreadLocal 是 Java 中一个非常重要的类,它为解决多线程程序的并发问题提供了一种新的思路。ThreadLocal 并不是一个 Thread,而是 Thread 的局部变量,它为每个使用该变量的线程提供独立的变量...
ThreadLocal 相关知识点 ThreadLocal 是 Java 语言中的一种机制,用于提供线程内部的局部变量。在多线程环境下,ThreadLocal 变量可以保证各个线程的变量相对独立于其他线程内的变量。这种机制可以帮助开发者在多...
ThreadLocal是Java编程语言中的一个线程局部变量类,它为每个线程提供了一个独立的变量副本,使得每个线程可以独立地改变自己的副本,而不会影响其他线程所对应的副本。这个特性在多线程环境下处理并发问题时非常...
Java中的ThreadLocal类是一个强大的工具,它允许程序员创建线程局部变量。这意味着每个线程都有其自己独立的、不可见的变量副本,从而避免了线程间的数据共享问题,简化了多线程环境下的编程复杂性。ThreadLocal并不...
Java ThreadLocal使用案例详解 Java ThreadLocal是Java语言中的一种机制,用于为每个线程提供一个独立的变量副本,以解决多线程环境下共享变量的线程安全问题。在本文中,我们将详细介绍Java ThreadLocal的使用案例...
Java ThreadLocal用法实例详解 Java ThreadLocal是Java中的一种线程局部变量机制,用于保存每个线程独有的数据,以避免线程之间的数据共享问题。ThreadLocal的基本使用非常简单,只需要定义一个ThreadLocal变量,...
彻底理解Java中的ThreadLocal ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量。使用这个工具类可以很简洁地编写出优美的多线程程序。ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这...