这个类在java1.2中就出现了,线程独有的变量(每个线程都有一份变量),使用它的好处之一就是可以少传许多参数。

在哪里用到它呢?有连接池的地方就有它的身影,连接池包括数据库连接池,网络连接池等。

import java.util.UUID;

class Factory {
    static ThreadLocal<String> connection=new ThreadLocal<>();
    static String getConnection() {
        String s=connection.get();
        if (s == null) {
            connection.set(UUID.randomUUID().toString());
        }
        return connection.get();
    }
}
public class TestThreadLocal {
    static void f() {
        String s = Factory.getConnection();
        System.out.println("f :" + s);
        g();
    }
    static void g() {
        String s = Factory.getConnection();
        System.out.println("g :" + s);
    }
    public static void main(String[] args) {
        new Thread(() -> f()).start();
        new Thread(() -> f()).start();
    }
}

输出结果:

f :6c71fba2-8fd6-4de9-88f9-69023290e213
f :c315c241-b379-446d-8159-dc758f020a80
g :c315c241-b379-446d-8159-dc758f020a80
g :6c71fba2-8fd6-4de9-88f9-69023290e213

ThreadLocal<String>connection这个变量其实就是一个马甲,它是唯一的一份(因为它是静态的呀)。这唯一的一份就相当于一个线程大管家,它负责去访问当前线程。请看ThreadLocal#get方法

public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

第一步,它会去获取当前线程t

第二步,通过当前线程t获取ThreadLocalMap对象map

第三步,如果没有map,那就给当前线程new出来一个并赋上初值(通过setInitialValue来实现);如果已经存在,那就读取之。

ThreadLocalMap这个类是一个内部静态类,全名是:ThreadLocal.ThreadLocalMap,其内部元素的键就是this(也就是ThreadLocal实例,即上例中的connection变量),值是Object类型的实例。

    Entry(ThreadLocal<?> k, Object v)

Thread这个类大名鼎鼎,它内部有一个成员变量:

    ThreadLocal.ThreadLocalMap threadLocals = null;

上例中,线程1和线程2各有一份ThreadLocalMap成员变量threadLocals,这两个threadLocals中都有同一份键:connection,但是它们的值不是同一份。

每一个线程都维持一份ThreadLocalMap threadLocals,ThreadLocal这个大管家负责访问当前线程对象的threadLocals变量

可见,ThreadLocal机制是纯java代码,没有底层实现,我们自己也是可以实现的,这是一种巧妙地机制。

ThreadLocal和ThreadLocalMap在同一个文件里面并且ThreadLocalMap是ThreadLocal的静态内部类,然后Thread又有ThreadLocalMap的成员变量,最后ThreadLocal变量作为一个大管家去访问ThreadLocalMap。这个API设计的真是合理,就该这么整啊!实现起来简简单单,却带来许多便利。

ThreadLocal类学习笔记的更多相关文章

  1. System类学习笔记

    最近在学习源码的过程中发现:很多深层次的代码都用到了一个类System类,所以决定对System类一探究竟 本文先对System类进行了剖析,然后对System类做了总结 一.首先对该类的中的所有字段 ...

  2. zt C++ list 类学习笔记

    C++ list 类学习笔记 分类: C++ 2011-09-29 00:12 7819人阅读 评论(0) 收藏 举报 listc++iteratorvectorcconstructor 双向循环链表 ...

  3. GUI学习之五——QAbstractButton类学习笔记

    今天总结一下AbstractButton类的学习笔记. 一.描述 AbstractButton是对各种按键的抽象类他的继承关系是这样的 首先,QAbstractButton继承了QWidget类的各种 ...

  4. java.util.Properties类 学习笔记

    学习目标:   1.认识properties文件,理解其含义,会正确创建properties文件. 2.会使用java.util.Properties类来操作properties文件. 3.掌握相对路 ...

  5. Java ThreadLocal类学习

    ThreadLocal为线程局部变量,通过线程名(key)-对象(value)的Map来获取每个线程对应的对象.我们不能通过ThreadLocal处理多线程并发问题,但是每个线程可以通过ThreadL ...

  6. PHP-解析验证码类--学习笔记

    1.开始 在 网上看到使用PHP写的ValidateCode生成验证码码类,感觉不错,特拿来分析学习一下. 2.类图 3.验证码类部分代码 3.1  定义变量 //随机因子 private $char ...

  7. C++ list 类学习笔记

    双向循环链表list list是双向循环链表,,每一个元素都知道前面一个元素和后面一个元素.在STL中,list和vector一样,是两个常被使用的容器.和vector不一样的是,list不支持对元素 ...

  8. 转载:C++ vector 类学习笔记

    声明:本文转载自http://blog.csdn.net/whz_zb/article/details/6827999 vector简介 vector是STL中最常见的容器,它是一种顺序容器,支持随机 ...

  9. 转载:C++ list 类学习笔记

    声明:本文转自http://blog.csdn.net/whz_zb/article/details/6831817 双向循环链表list list是双向循环链表,,每一个元素都知道前面一个元素和后面 ...

随机推荐

  1. Getaddrinfo()笔记

    WSADATA dwRetval; if (WSAStartup(MAKEWORD(2,2),&dwRetval)!=0) //开启Socket { printf("WSAStart ...

  2. ubuntu将命令写在一个文件里,执行文件,source命令

    source命令也称为“点命令”,也就是一个点符号(.).source命令通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录.用法: source filename 或 . fil ...

  3. Apache

    一.简介 Apache是世界使用排名第一的Web服务器软件.它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一.它快速.可靠并且可通过简单的A ...

  4. C++变量和函数

    变量可根据作用域和类型分为 (动态)全局变量,静态全局变量,(动态)局部变量,静态局部变量 全局变量:定义在函数外,在源程序其他cpp文件中访问需要extern修饰 静态局部变量:生命周期相比局部变量 ...

  5. 浅谈Java泛型之<? extends T>和<? super T>的区别

    关于Java泛型,这里我不想总结它是什么,这个百度一下一大堆解释,各种java的书籍中也有明确的定义,只要稍微看一下就能很快清楚.从泛型的英文名字Generic type也能看出,Generic普通. ...

  6. [转]How to add new table in NopCommerce

    本文转自:http://www.tech-coder.com/2015/07/how-to-add-new-table-in-nopcommerce.html Hey guys I am back a ...

  7. system generator 卷积编码器快速设计

    卷积码 卷积码是一种特殊的编码方式,不仅与当前的输入有关,还与之前的输入有关.可以用一个多项式来表示一个卷积编码,多项式表示有多少个移位寄存器以及他们怎么与模2加法器相连.比如,下图中的无反馈的卷积编 ...

  8. 《JavaScript权威指南 第六版 中文版》(一)

    <JavaScript权威指南 第六版 中文版> 第二章 词法结构 2.1字符集 JavaScript是使用Unicode字符集编码写的. 2.1.1区分大小写 JavaScript是区分 ...

  9. 第16章 调色板管理器_16.4 一个DIB位图库的实现(1)

    16.4.1自定义的 DIBSTRUCT结构体 字段 含义 PBYTE *ppRow ①指向位图视觉上最上面的一行像素.(不管是自下而上,还是自上而下) ②放在第一个字段,为的是后面定义宏时可方便访问 ...

  10. JavaScript(DOM操作)(Window.document对象)

    一.找到元素: docunment.getElementById("id"):                      根据id找,最多找一个: var a =docunment ...