`
liudeh_009
  • 浏览: 242751 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

ThreadLocal使用及原理解析

    博客分类:
  • JDK
阅读更多

 

1.ThreadLocal干什么的?
      我们知道,在多线程程序中,同一个线程在某个时间段只能处理一个任务.我们希望在这个时间段内,任务的某些变量能够和处理它的线程进行绑定,在任务需要使用这个变量的时候,这个变量能够方便的从线程中取出来.ThreadLocal能很好的满足这个需求,用ThreadLocal变量的程序看起来也会简洁很多,因为减少了变量在程序中的传递.
 
2.ThreadLocal的原理是怎么样的?
    每个运行的线程都会有一个类型为ThreadLocal.ThreadLocalMap的map,这个map就是用来存储与这个线程绑定的变量,map的key就是ThreadLocal对象,value就是线程正在执行的任务中的某个变量的包装类Entry.
 
3. ThreadLocal保存变量的生命周期是怎么样的?
    ThreadLocal保存变量的生命周期 <=任务的生命周期<=线程的生命周期
 
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); 
    }
  threadLocalHashCode的值即为 Threadlocal对象的hashcode值,从上面可以知道,
   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;
                }
            }
        }
     从上可以看到,调用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,从而造成内存泄露
 
 
   

 

  • 大小: 79.9 KB
分享到:
评论

相关推荐

    使用ThreadLocal管理“session”数据

    要深入理解ThreadLocal的工作原理,需要查看其源码。ThreadLocal内部使用了一个ThreadLocalMap,它是一个基于ThreadLocal实例作为键,值为用户存储对象的弱引用表。每个线程都有一个这样的ThreadLocalMap,保证了...

    Java源码解析ThreadLocal及使用场景

    Java源码解析ThreadLocal及使用场景 ThreadLocal是Java中一个非常重要的类,它在多线程环境下经常使用,用于提供线程本地变量。这些变量使每个线程都有自己的一份拷贝,使得多个线程可以独立地使用变量,不会彼此...

    Android 详解ThreadLocal及InheritableThreadLocal

    本文将深入解析这两个概念以及它们在Android环境下的工作原理。 **ThreadLocal** 是一个线程局部变量,它为每个线程提供独立的副本。这意味着每个线程都拥有ThreadLocal变量的私有实例,它们之间互不干扰。在...

    正确理解ThreadLocal.pdf

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

    threadLocal

    以上内容涵盖了从ThreadLocal原理到其在实际开发中的应用,以及相关的多线程、并发编程、HTTP通信等知识点。通过阅读和理解这些资料,开发者可以深化对ThreadLocal的理解,并将其有效地应用于项目中。

    java ThreadLocal使用案例详解

    ThreadLocal的工作原理 那么,ThreadLocal是如何工作的呢?当我们使用ThreadLocal时,实际上是将变量存储在ThreadLocalMap中。每个线程都可以拥有自己的ThreadLocalMap,从而避免了共享变量的线程安全问题。 ...

    ThreadLocal详解

    ### ThreadLocal详解:Java多线程中的线程局部变量 #### 重要概念解析:ThreadLocal在Java多线程中的角色 ...理解并掌握ThreadLocal的工作原理和使用技巧,对于Java开发者而言,是提高多线程编程水平的关键步骤之一。

    JAVA并发-自问自答学ThreadLocal.pdf

    1. **ThreadLocal的工作原理**: - 每个ThreadLocal实例都会为每一个线程创建一个单独的变量副本。当线程访问ThreadLocal的get()或set()方法时,实际上是访问的是与当前线程绑定的副本,而不是全局唯一的变量。 - ...

    InheritableThreadLocal & ThreadLocal

    《InheritableThreadLocal & ThreadLocal 深度解析》 在Java编程中,线程局部变量(ThreadLocal)和可继承线程局部变量(InheritableThreadLocal)是两种非常重要的工具,它们允许我们在多线程环境中创建独立于线程...

    Java并发编程原理与实战

    Condition的使用及原理解析.mp4 使用Condition重写waitnotify案例并实现一个有界队列.mp4 深入解析Condition源码.mp4 实战:简易数据连接池.mp4 线程之间通信之join应用与实现原理剖析.mp4 ThreadLocal 使用及实现...

    Android 中ThreadLocal的深入理解

    ThreadLocal在Android开发中是一个非常重要的工具类,用于在多线程环境中提供线程局部变量。它的核心概念在于,每个...了解ThreadLocal的工作原理和使用场景,可以帮助开发者更好地管理和优化多线程环境中的数据存储。

    Python threading.local代码实例及原理解析

    # 创建全局ThreadLocal对象 localVal = threading.local() # 在主线程中初始化 localVal.val = "Main-Thread" def process_student(): print(f'{localVal.val} (in {threading.current_thread().name})') def ...

    龙果 java并发编程原理实战

    第31节Condition的使用及原理解析00:17:40分钟 | 第32节使用Condition重写wait/notify案例并实现一个有界队列00:22:05分钟 | 第33节深入解析Condition源码00:21:15分钟 | 第34节实战:简易数据连接池00:24:53分钟...

    Java 并发编程原理与实战视频

    第31节Condition的使用及原理解析00:17:40分钟 | 第32节使用Condition重写wait/notify案例并实现一个有界队列00:22:05分钟 | 第33节深入解析Condition源码00:21:15分钟 | 第34节实战:简易数据连接池00:24:53分钟...

    苍穹外卖-共享当前登录用户ID.docx

    `ThreadLocal`是一种Java内置的线程局部变量,它为每一个使用该变量的线程都提供了一个独立的变量副本,从而避免了多线程环境下的数据竞争问题。这使得`ThreadLocal`非常适合用来保存每个线程特有的数据,例如本例中...

    servlet+tomcat面试题及答案解析.rar

    以下是一些常见的Servlet和Tomcat相关的面试题及答案解析: 1. **什么是Servlet?** Servlet是Java编程语言中用于扩展服务器功能的接口,由Java Servlet API定义。它允许程序员编写运行在服务器端,处理客户端请求...

    龙果java并发编程完整视频

    第31节Condition的使用及原理解析00:17:40分钟 | 第32节使用Condition重写wait/notify案例并实现一个有界队列00:22:05分钟 | 第33节深入解析Condition源码00:21:15分钟 | 第34节实战:简易数据连接池00:24:53分钟...

    java并发编程

    第31节Condition的使用及原理解析00:17:40分钟 | 第32节使用Condition重写wait/notify案例并实现一个有界队列00:22:05分钟 | 第33节深入解析Condition源码00:21:15分钟 | 第34节实战:简易数据连接池00:24:53分钟...

Global site tag (gtag.js) - Google Analytics