ThreadLocal类学习笔记

这个类在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设计的真是合理,就该这么整啊!实现起来简简单单,却带来许多便利。

时间: 2024-08-27 18:51:30

ThreadLocal类学习笔记的相关文章

Apache commons lang工具类学习笔记(2)--StringUtils

StringUtils工具类具有对String具有简单而强大的处理能力,从检查空串到分割字符串,到生成格式化的字符串,使用都很方便简洁,能减少很多代码量; 详细的使用方法可以参考下面的例子或者官方的API(http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/StringUtils.html#isAlpha(java.lang.CharSequence)) packa

Java Object类学习笔记

看下Api文档的一些说明 public class Object Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class. Since: JDK1.0 从JDK1.0就已经存在的元老类,类结构的根,所有类的父类,所有类都实现了这个类的方法,包含

Collection类学习笔记

binarySearch原理: public static index halfSearch(List<String> list, String key) { int max,min,mid; max = list.size()-1; min = 0; while(min<=max) { mid = (max+min) >>1; String str = list.get(mid); int num = str.compareTo(key); if(num > 0) m

Arrays类学习笔记

Arrays.asList(arr); 该方法可以把数组变成List集合. String[] arr = {"abc","cc"}; List<String> list = Arrays.asList(arr); /* 如果数组中的元素都是对象,那么变成集合的时候,数组中的元素就直接转换成集合中的元素. 如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在. */ Arrays.toArray(new String[]); 1. 指定类型

C++类学习笔记

在C++中struct类型(结构体)属于类类型. class student {} 与 strcut student {}是一样的,唯一的区别就是class中如果未对成员进行public.private或protected等访问限定声明则默认为private的,而struct中则默认为public.类同样遵循结构体的字节对齐原则. 私有的成员函数只能被类内的其他成员函数调用,即使是其对象也不行.私有的成员变量只能被本类的成员函数和(友元类)所调用.友元类后续补充. 受保护的成员则可以被本类以及派

java.util.Properties类 学习笔记

学习目标: 1.认识properties文件,理解其含义,会正确创建properties文件. 2.会使用java.util.Properties类来操作properties文件. 3.掌握相对路径,能正确书写一个properties文件的相对路径. 一.认识properties文件 1.properties文件是一个文本文件 2.properties文件的语法有两种,一种是注释,一种属性配置. 注    释:前面加上#号 属性配置:以“键=值”的方式书写一个属性的配置信息. 3.propert

java System类学习笔记

java 中 System 类 最常见到 System.out.println(); System类 定义为 public final class System extends Object{} 包含几个有用的类字段和方法,用了关键字 final 修饰,表示此类不能被其他类继承. 其构造方法为 private System{} (构造方法私有化,不能被外部实例化). System 中有三个属性:in,out,err: 1.private final static InputStream in=n

C++ string 类 学习笔记

string类型支持长度可变的字符串,C++标准库将负责管理与存储字符相关的内存,以及提供各种有用对的操作.标准库string类型的目的就是满足对字符串的一般应用. 1.string对象的定义和初始化 通过string类的构造函数来进行初始化. 常用的有: //默认构造函数,s1为空串 string s1; //将s2初始化s1的一个副本 string s2(s1); //将s3初始化为一个字符串字面值副本 string s3("value"); //将s4初始化为字符'c'的n个副本

C++ list 类学习笔记(转载)

双向循环链表list list是双向循环链表,,每一个元素都知道前面一个元素和后面一个元素.在STL中,list和vector一样,是两个常被使用的容器.和vector不一样的是,list不支持对元素的任意存取.list中提供的成员函数与vector类似,不过list提供对表首元素的操作push_front.pop_front,这是vector不具备的.和vector另一点不同的是,list的迭代器不会存在失效的情况,他不像vector会保留备份空间,在超过容量额度时重新全部分配内存,导致迭代器