赞
踩
经过学习和理解,总结了以下经验:
真正的主角是线程上下文,而不是ThreadLocal
ThreadLocal的本质是实现Java线程私有map变量的一个工具类,所以,提供的最核心的方法就是set和get
如果引入线程上下文的概念,那么,ThreadLocal就是实现线程上下文功能的工具类
本文主要的目的是实现ThreadLocal的入门,基于自己的理解给出一个比较容易懂的ThreadLocal定义,并且结合线程上下文的概念,给出ThreadLocal的定位。本文主要包括以下内容:
This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its {@code get} or {@code set} method) has its own, independently initialized copy of the variable. {@code ThreadLocal} instances are typically private
static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).
Threadlocal 提供了线程本地私有的变量,通过get和set方法可以对变量进行操作,每个线程之间的Thread-Local变量是相互独立的。一般来说,ThreadLocal都是私有静态属性,用来存储一些需要和线程绑定的数据,比如事务ID,用户ID。
Each thread holds an implicit reference to its copy of a thread-local
variable as long as the thread is alive and the {@code ThreadLocal}
instance is accessible; after a thread goes away, all of its copies of
thread-local instances are subject to garbage collection (unless other
references to these copies exist).
每个线程持有对ThreadLocal变量的引用,只要线程存在,这个变量就一直存在。如果线程对象被回收,则Thread-Local 变量在没有别的引用的情况下也会被回收。
注意,ThreadLocal≠thread-local变量,在后面的描述中可以发现,ThreadLocal和thread-local变量是key-value的关系,共同存在Thread维护的map中。
小结:
所以,从本质上讲,就要把ThreadLocal理解成一个工具类,它并不存储数据,只是提供了让线程存储私有数据的方法。
根据上面的分析,在理解ThreadLocal时最容易犯的错误就是:
所以,要理解ThreadLocal,首先要下一个自己能够理解的定义,目前来说,我对于ThreadLocal的定义就是:
ThreadLocal就是一个工具类,为Thread对象提供了私有变量的操作方法
基于这个定义,就可以从工具类的角度去理解,而不需要关心各种key-value关系,理解起来还比较顺畅。
使用ThreadLocal编程的思路和一般使用工具类没有太大的区别
在编程的过程中,重点不要放在ThreadLocal上,而应该放在它提供的set和get方法以及线程的私有变量逻辑上
public class ThreadLocalDemo {
public static final ThreadLocal<String> tl = new ThreadLocal<String>();
public static void main(String[] args) {
//创建一个线程,操作私有变量
Thread t1 = new Thread(() -> {
tl.set("线程1私有变量");
System.out.println(Thread.currentThread() + "---" + tl.get());
});
t1.start();
//set方法在哪里执行,私有变量就存到哪个线程对象中
tl.set("主线程私有变量");
System.out.println(Thread.currentThread() + "---" + tl.get());
}
}
真正有价值的是线程上下文,ThreadLocal只是实现线程上下文的一种方式而已
特性决定用途,共享特性和私有特性支持了线程上下文用于事务、全局session等场景。
在事务场景中使用,利用的是线程私有的特性
如果连接池,在事务的场景中,在Service层需要开启事务和关闭事务,在DAO层需要基于数据库连接操作数据。在Service和DAO中,必须使用同一个连接,不然就无法控制事务。
如果不加任何控制,在Service层和DAO层获取到的连接对象可能都不是同一个,所以,在单次业务流程中,是一个线程执行的,每个线程必须独享一个连接,直到业务结束。
因此,在获取连接的方法中,需要将连接放到本线程的私有map中,使用ThreadLocal刚好可以实现。
注意:
在session和token场景中使用ThreadLocal使用的是共享特性,由于所有的方法中都有可能要用session,所以使用上下文共享特性,可以简化代码,这里不是为了私有,而是为了共享。
大致流程如下:
示例图如下:参考链接
小结:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。