官方对ThreadLocal的描述:

  "该类提供了线程局部(thread-local)变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其get或set方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal实例通常是类中的private static字段,它们希望将状态与某一个线程(例如,用户ID或事物ID)相关联。"

《Thinking in Java》中的描述:

  防止任务在共享资源上产生冲突的第二种方式是根除对变量的共享。线程本地存储是一种自动化机制,可以为使用变量的每个不同的线程都创建不同的存储。因此,如果你有5个线程都要使用变量x所表示的对象,那线程本地存储就会生成5个用于x的不同的存储块。主要是,它们使得你可以将状态与线程关联起来。

三个要点:

  1.每个线程都有自己的局部变量

    每个线程都有一个独立于其它线程的上下文来保存这个变量,一个线程的本地变量对其它线程是不可见的。

  2.独立于变量的初始化副本

    ThreadLocal可以给一个初始值,而每个线程都会获得这个初始化值的一个副本,这样才能保证不同的线程都有一份拷贝。

  3.状态与某一个线程相关联

    ThreadLocal不是用于解决共享变量的问题的,不是为了协调线程同步而存在,而是为了方便每个线程处理自己的状态而引入的一个机制,就像《Thinking in Java》中描述的那样:”它们使得你可以将状态与线程关联起来。“理解这点对正确使用ThreadLocal至关重要。

源码举例:

  从输出的结果可以看出,五个线程处理自己的本地变量值。

  而这个测试的结果,并没有相同。这是因为实例为对象,所以初始值为一个对象的引用,那么五个线程的副本就是这个对象的引用的副本,也就是说这些引用还是指向同一个对象,所以就出现了这种情况。

ThreadLocal的接口方法:

  • void set(T value):设置当前线程的线程局部变量的值;
 public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); if (map != null)
  map.set(this, value);
  //说明线程第一次使用线程本地变量(注意这里的第一次含义)
else
createMap(t, value);
}
  • public T get():该方法返回当前线程所对应的线程局部变量;
 public T get() {
  //获取当前执行线程
  Thread t = Thread.currentThread();
  //取得当前线程的ThreadLocalMap实例
  ThreadLocalMap map = getMap(t);
  //如果map不为空,说明该线程已经有了一个ThreadLocalMap实例
  if (map != null) {
    //map中保存线程的所有的线程本地变量,我们要去查找当前线程本地变量
    ThreadLocalMap.Entry e = map.getEntry(this);
    //如果当前线程本地变量存在这个map中,则返回其对应的值
11     if (e != null)
  return (T)e.value;
13   }
//如果map不存在或者map中不存在当前线程本地变量,返回初始值
return setInitialValue();
}
  • public void remove():将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。当线程结束后,对应该线程的局部变量将被自动垃圾回收,所以显示调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度;
  • protected T initialValue():返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的,这个方法是一个延迟调用方法,在线程第1次调用get()或set(T)时才执行,并且仅执行1次。ThreadLocal中的默认实现直接返回一个null。

这里注意,ThreadLocal中是有一个Map,但这个Map不是我们平时使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一个内部类,不对外使用的。当使用ThreadLocal存值时,首先是获取到当前线程对象,然后获取到当前线程本地变量Map,最后将当前使用的ThreadLocal和传入的值放到Map中,也就是说ThreadLocalMap中存的值是[ThreadLocal对象, 存放的值]这样做的好处是,每个线程都对应一个本地变量的Map,所以一个线程可以存在多个线程本地变量。下面提供一个简单的实现版本:

Java中ThreadLocal的深入理解的更多相关文章

  1. java中threadlocal的理解

    [TOC] #java中threadlocal的理解##一.threadlocal的生命周期和ThreadLocalMap的生命周期可以吧TreadLocal看做是一个map来使用,只不过这个map是 ...

  2. Java中线程同步的理解 - 其实应该叫做Java线程排队

    Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可 ...

  3. java中线程同步的理解(非常通俗易懂)

    转载至:https://blog.csdn.net/u012179540/article/details/40685207 Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运 ...

  4. java中ThreadLocal的使用

    文章目录 在Map中存储用户数据 在ThreadLocal中存储用户数据 java中ThreadLocal的使用 ThreadLocal主要用来为当前线程存储数据,这个数据只有当前线程可以访问. 在定 ...

  5. java中ThreadLocal类的使用

    ThreadLocal是解决线程安全问题一个很好的思路,ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本,由于Key值不可重复, ...

  6. 微冷的雨之Java中的多线程初理解(一)

    在讲解多线程前,我们必须理解什么是多线程?而且很多人都会将进程和线程做对比. 进程和线程 进程:进程是操作系统结构的基础,是一次程序的执行,是一个程序及其数据在处理机上顺序执行时所发生的活动,是程序在 ...

  7. 对Java中字符串的进一步理解

    字符串在程序开发中无处不在,也是用户交互所涉及到最频繁的数据类型,那么字符串不仅仅就是我们简单的理解的String str = "abc";一起来更加深入的看一下 在Java中,字 ...

  8. Java中ThreadLocal的设计与使用

    早在Java 1.2推出之时,Java平台中就引入了一个新的支持:java.lang.ThreadLocal,给我们在编写多线程程序时提供了一种新的选择.使用这个工具类可以很简洁地编写出优美的多线程程 ...

  9. Java学习疑惑(8)----可视化编程, 对Java中事件驱动模型的理解

    我们编写程序就是为了方便用户使用, 我觉得UI设计的核心就是简洁, 操作过于繁琐的程序让很大一部分用户敬而远之. 即使功能强大, 但是人们更愿意使用易于操作的软件. 近年流行起来的操作手势和逐渐趋于成 ...

随机推荐

  1. GridControl的列显示成图片+文字,并且不同的文字对应不同的图片

    public static void SetDispatchStatus(GridView aGridView1, GridColumn aColStatus, bool aOnlyImage) { ...

  2. springMVC视频教程

    http://edu.51cto.com/index.php?do=lession&id=42165

  3. redhat6修改主机名

    1.临时修改主机名 sudo hostname lyhost 2.永久修改主机名 vim /etc/sysconfig/network 修改里面的hostname字段即可,重启后生效.

  4. VBA高效删除不连续多行

    最近在搞VBA,在感叹Excel功能强大的同时,对于新接触的一门编程语言也很烦恼.很多基础的语法都要靠网上搜索.现总结一些学习到的心得. VBA高效删除不连续多行 在一个拥有几万条数据的Excel中, ...

  5. android 矩阵处理类:Matrix

    在Android中,对图片的处理需要使用到Matrix类,Matrix是一个3 x 3的矩阵,他对图片的处理分为四个基本类型: 1.Translate 2.Scale 3.Rotate 4.Skew ...

  6. CSS3:empty

    :empty ---空的元素样式 <!DOCTYPE html> <html> <head lang="en"> <meta charse ...

  7. Java应用发布后,需要关注的7个性能指标

    在某个重大发布之后,都需要记录相应的指标,本文介绍了最重要的几个 Java 性能指标,包括响应时间和平均负载等.为理解应用程序在生产环境中如何运行,就需要遵循一些 Java 性能指标. 在以前,当软件 ...

  8. Line Search and Quasi-Newton Methods 线性搜索与拟牛顿法

    Gradient Descent 机器学习中很多模型的参数估计都要用到优化算法,梯度下降是其中最简单也用得最多的优化算法之一.梯度下降(Gradient Descent)[3]也被称之为最快梯度(St ...

  9. wait、waitpid 僵尸进程 孤儿进程

    man wait: NAME wait, waitpid, waitid - wait for process to change state SYNOPSIS #include <sys/ty ...

  10. JVM的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集

    (转自:http://my.oschina.net/u/436879/blog/85478) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认 ...