`

ThreadLocal

阅读更多

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的应用及源代码解析    
Java代码  收藏代码
  1. public class UserContextHolder {  
  2.   private static final ThreadLocal<User>  userThreadLocal = new ThreadLocal<User>();  
  3.     
  4.   public static  User get(){  
  5.       return userThreadLocal.get();  
  6.   }  
  7.     
  8.   public static void set(User user){  
  9.        userThreadLocal.set(user);  
  10.   }  
  11. }  
    
UserContextHolder的get方法最终会调用ThreadLocal的get方法,ThreadLocal的get方法如下:
Java代码  收藏代码
  1. public T get() {  
  2.     Thread t = Thread.currentThread();//取得当前的thread  
  3.     ThreadLocalMap map = getMap(t);//取得当前thread的ThreadLocalMap对象  
  4.     if (map != null) { //返回key为当前ThreadLocal的value值  
  5.         ThreadLocalMap.Entry e = map.getEntry(this);  
  6.         if (e != null)  
  7.             return (T)e.value;  
  8.     }  
  9.     return setInitialValue();//返回默认值null  
  10. }  
 
 ThreadLocalMap 的key为当前的Threadlocal对象,Threadlocal对象的hashcode实现如下:
Java代码  收藏代码
  1. private final int threadLocalHashCode = nextHashCode();  
  2.   
  3. private static AtomicInteger nextHashCode = new AtomicInteger();  
  4.   
  5. private static final int HASH_INCREMENT = 0x61c88647;  
  6.     
  7. private static int nextHashCode() {  
  8.     return nextHashCode.getAndAdd(HASH_INCREMENT);   
  9.     }  
  threadLocalHashCode的值即为 Threadlocal对象的hashcode值,从上面可以知道,
   Threadlocal对象的hashcode值是递增的,是HASH_INCREMENT的N倍.这个也和以前遇到的hashcode的生成方式不一样
 
  UserContextHolder的set方法最终会调用ThreadLocal的set方法,ThreadLocal的set方法如下:
Java代码  收藏代码
  1. public void set(T value) {  
  2.     Thread t = Thread.currentThread();  
  3.     ThreadLocalMap map = getMap(t);//取得当前线程对应的ThreadLocalMap   
  4.     if (map != null)  //ThreadLocalMap不空,把value以当前ThreadLocal为key放到ThreadLocalMap 中  
  5.         map.set(this, value);  
  6.     else  //创建一个ThreadLocalMap.并把value放到ThreadLocalMap中  
  7.         createMap(t, value);  
  8. }  
     
   ThreadLocal还有一个常用的方法remove,如下:
Java代码  收藏代码
  1. public void remove() {  
  2.     ThreadLocalMap m = getMap(Thread.currentThread());  
  3.     if (m != null)  
  4.         m.remove(this);  
  5. }  
 
Java代码  收藏代码
  1.    /** 
  2.       * Remove the entry for key. 
  3.       */  
  4.      private void remove(ThreadLocal key) {  
  5.          Entry[] tab = table;  
  6.          int len = tab.length;  
  7.          int i = key.threadLocalHashCode & (len-1);  
  8.          for (Entry e = tab[i];  
  9. e != null;  
  10. e = tab[i = nextIndex(i, len)]) {  
  11.              if (e.get() == key) {  
  12.                  e.clear();  
  13.                  expungeStaleEntry(i);  
  14.                  return;  
  15.              }  
  16.          }  
  17.      }  
     从上可以看到,调用ThreadLocal的remove方法后,当前存放的Entry会从map中清除
 
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并不是一个变量,而是一个类,它为每个线程都创建了一个独立的变量副本,使得每个线程都...

    ThreadLocal 内存泄露的实例分析1

    在 `LeakingServlet` 的 `doGet` 方法中,如果 `ThreadLocal` 没有设置值,那么会创建一个新的 `MyCounter` 并设置到 `ThreadLocal` 中。关键在于,一旦 `MyCounter` 被设置到 `ThreadLocal`,那么它将与当前线程...

    java事务 - threadlocal

    Java事务和ThreadLocal是两种在Java编程中至关重要的概念,它们分别用于处理多线程环境下的数据一致性问题和提供线程局部变量。 首先,我们来深入理解Java事务。在数据库操作中,事务是一系列操作的集合,这些操作...

    正确理解ThreadLocal.pdf

    ### 正确理解ThreadLocal:深入解析其工作原理与应用场景 #### 一、ThreadLocal的基本概念 `ThreadLocal`是Java平台提供的一种线程局部变量的解决方案,它为每一个使用该变量的线程都提供了独立的变量副本,使得每...

    ThreadLocal的几种误区

    ThreadLocal是Java编程中一种非常特殊的变量类型,它主要用于在多线程环境下为每个线程提供独立的变量副本,从而避免了线程间的数据共享和冲突。然而,ThreadLocal在理解和使用过程中容易产生一些误区,这里我们将...

    threadLocal

    ThreadLocal是Java编程语言中的一个线程局部变量类,它为每个线程提供了一个独立的变量副本,使得每个线程可以独立地改变自己的副本,而不会影响其他线程所对应的副本。这个特性在多线程环境下处理并发问题时非常...

    java中ThreadLocal详解

    ### Java中ThreadLocal详解 #### 一、ThreadLocal概述 在Java多线程编程中,`ThreadLocal`是一个非常重要的工具类,它提供了一种在每个线程内部存储线程私有实例的方法。通常情况下,当多个线程共享某个变量时,...

    ThreadLocal整理.docx

    ThreadLocal 整理 ThreadLocal 是 Java 中的一个重要组件,它能够在每个线程中保持独立的副本。这个功能是通过 Thread 类中的 threadLocals 属性来实现的,这个属性实际上是一个 Entry 数组,其中的每个 Entry 都...

    事务的封装和Threadlocal实例

    private static final ThreadLocal&lt;Connection&gt; connectionHolder = new ThreadLocal(); public static void setConnection(Connection conn) { connectionHolder.set(conn); } public static Connection get...

    java 简单的ThreadLocal示例

    Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,尤其在处理线程间数据隔离和共享时。ThreadLocal不是线程本身,而是为每个线程提供一个独立的变量副本,使得每个线程都可以独立地改变...

    设计模式及ThreadLocal资料

    本资料主要聚焦于两种设计模式以及Java中的ThreadLocal特性。 首先,我们来探讨单例模式。单例模式是一种确保一个类只有一个实例,并提供全局访问点的设计模式。在Java中,通常通过私有构造函数、静态工厂方法或...

    ThreadLocal原理及在多层架构中的应用

    **线程局部变量(ThreadLocal)是Java编程中一个非常重要的概念,主要用于在多线程环境中为每个线程提供独立的变量副本。ThreadLocal不是一种数据结构,而是一种解决线程间共享数据的方式,它提供了线程安全的局部...

    使用ThreadLocal管理“session”数据

    在Java编程中,ThreadLocal是线程局部变量的类,它提供了一种在多线程环境中为每个线程创建和维护独立副本的机制。ThreadLocal主要用于解决线程间的数据隔离问题,确保各线程拥有自己的变量副本,避免了数据共享带来...

    java中ThreadLocal类的使用

    Java中的`ThreadLocal`类是一个非常实用的工具,它提供了线程局部变量的功能。线程局部变量意味着每个线程都拥有自己独立的变量副本,互不干扰,这在多线程编程中尤其有用,可以避免数据共享带来的同步问题。下面...

    Quartz-ThreadLocal.rar

    这个压缩包 "Quartz-ThreadLocal.rar" 内含的学习资源很可能是关于如何在 Quartz 调度器中结合使用 ThreadLocal 的示例。 Quartz 的核心功能包括: 1. **作业与触发器**:在 Quartz 中,任务被称为“作业”(Job)...

    JDK的ThreadLocal理解(一)使用和测试

    **标题:“JDK的ThreadLocal理解(一)使用和测试”** **正文:** ThreadLocal是Java中的一个非常重要的线程安全工具类,它在多线程编程中扮演着独特的角色。通过创建ThreadLocal实例,我们可以为每个线程提供一个...

    Java中ThreadLocal的设计与使用

    Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,用于为每个线程提供独立的变量副本。理解ThreadLocal的工作原理和使用方法对于编写高效、安全的多线程程序至关重要。 ### ...

Global site tag (gtag.js) - Google Analytics