这个类在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. android 导入数据(通讯录)

    接着android 中导出数据 一文,下面介绍在android中导入数据的思路: 1.将数据从文本中读取出来 2.封装处理成自己想要的对象或模型 3.将处理好的数据对象插入自己应用的数据库中 4.更新 ...

  2. 网络基本概念备忘:MAC地址,端口,HTTP状态码

    MAC地址 英文MAC Address 英文全称: Media Access Control Address 别称:硬件位址 用途:定义网络设备位置 表示:十六进制数,6 Byte 特点:产品出产后M ...

  3. CURL使用方法详解

    php采集神器CURL使用方法详解 作者:佚名  更新时间:2016-10-21   对于做过数据采集的人来说,cURL一定不会陌生.虽然在PHP中有file_get_contents函数可以获取远程 ...

  4. LINUX下NFS系统的安装配置

    准备:NFS系统服务器IP 192.168.135.1 ,NFS共享目录/mnt/NFS 一.安装NFS 查看nfs是否安装 #rpm -qa | grep nfs 若没有则安装nfs包 #yum i ...

  5. 【OpenWRT之旅】如何自定义一个配置文件的设置界面

    作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/ 1. 引言 OpenWRT中采用LuCI作为它的Web interface界面框架,采用Lua语言.在本文中将以 ...

  6. No resource found that matches the given name 'Theme.AppCompat.Light 的完美解决方案

    No resource found that matches the given name 'Theme.AppCompat.Light 的完美解决方案 首先这个问题的产生是由于缺少Theme.App ...

  7. ArrayList如何实现线程安全

    一:使用synchronized关键字,这个大家应该都很熟悉了,不解释了: 二:使用Collections.synchronizedList();使用方法如下: 假如你创建的代码如下:List< ...

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

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

  9. Jmeter :多个jmeter如何参数化获取不同的CSV文件

    如何为不同的jmeter engine建立不同的csv文件: 1.如果需要多个jmeter engine 去读取不同的csv文件,可以使用一个变量去区分 ${__P(InstanceID)},  in ...

  10. NODE.JS开发指南学习笔记2

    1.核心模块 核心模块是Node.js的心脏,由一些精简高效的库组成,为其提供了基本的API.2.全局对象 global.所有的的全局变量都是其属性.其根本的作用是作为全局变量的宿主.3.全局变量 1 ...