最开始的时候,理解的ThreadLocal,我的理解是这样的:
ThreadLocal<Thread,Map<k,v>> K的话是线程,V的话是线程的副本,是一个Map,里面可以方式多个变量的副本,后来发现是错的。
今天翻了一下代码,画了一个类图。
关于ThreadLocalMap.table这个属性,类型是Entry[]
用于真正存放数据的Entry,继承于WeakReference。想想ThreadLocal的使用场景,用“空间换时间”,若空间全部被强应用,则很容易造成内存泄露(使用结束后没有显示调用remove方法)。采用弱引用,在关键时刻,或在调用方没有显示的置空的情况下,也可回收部分内存,以便程序继续运行。其余基本都与HashMap的内部实现类似,内部都通过数组实现。而对键值key,HashMap存的是用户自定义的值,ThreadLocal存的线程对象hashcode值,仅此而已。
关于ThreadLocal中的方法
public void set(T value)
设置当前线程副本中的线程局部变量的值。
public T get()
返回此线程局部变量的当前线程副本中的值。
如果这是线程第一次调用该方法,则创建并初始化此副本。
public void remove()
移除此线程局部变量的值。
该方法是JDK 5.0新增的方法。目的是为了减少内存的占用。当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
protected T initialValue()
返回此线程局部变量的当前线程的初始值。
线程第一次使用get()方法访问变量的时候。如果线程先于get方法调用set(T)方法,则不会在线程中再调用initialValue方法。该方法是一个protected的方法,显然是为了让子类覆盖而设计的。因该缺省实现只返回null;如果程序员希望将线程局部变量初始化为 null 以外的某个值,则必须为 ThreadLocal 创建子类,并重写此方法。
关于ThreadLocal属性的get操作
1、获得当前线程对象
2、从当前线程中获得ThreadLocalMap的引用
3、然后通过当前ThreadLocal属性的hashCode找到对应的Entry,Entry是一个数组,真正存放数据的地方,返回结果
使用ThreadLocal注意的问题
1、变量污染问题
在使用线程池的时候,要非常主要remove的操作,如果没有,一个线程处理完一个任务,之后处理另外一个任务,变量就会有问题。
2、内存问题
主要放入ThreadLocal中的数据大小,虽然是弱引用,但是也会导致GC问题的。
相关推荐
**ThreadLocal源代码解析** `ThreadLocal`的`get`和`set`方法实际上依赖于`Thread`类中的一个`ThreadLocalMap`。当我们调用`set`方法时,`ThreadLocal`会将值存储在当前线程的`ThreadLocalMap`中,键为`ThreadLocal`...
源代码分析有助于深入理解其内部工作原理,优化应用性能,并进行自定义扩展。 1. **Struts2架构图** 请求在Struts2框架中的处理流程始于Filter链,其中Filter主要包括`ActionContextCleanUp`和`FilterDispatcher`...
具体差异需要查看对应版本的源代码来了解。 理解ThreadLocal的关键在于认识到它是线程局部的,每个线程都有自己的独立副本,而不是所有线程共享一个全局变量。这使得ThreadLocal成为在多线程环境下维护线程安全状态...
上述代码中,`doSomethingPrimary`和`doSomethingSecondary`方法会根据注解指定的数据源执行SQL操作。 5. **数据源上下文持有器** 需要创建一个`DataSourceContextHolder`类来保存当前线程的数据源key: ```java...
JavaSourceLearn是一个旨在深入解析Java源代码的开源项目。该项目的目标是帮助开发者更全面地理解Java平台的核心工作原理,从而提升编程技能和解决问题的能力。在这个项目中,作者将分享自己对Java源代码的个人理解...
书中通过实例解析这些概念,帮助读者建立起面向对象思维。 其次,异常处理是Java程序健壮性的重要保障。Java的异常体系包括检查型异常和运行时异常,学习如何正确地捕获和处理异常,可以预防程序在运行时出错。源码...
Java的源代码被编译成字节码,可以在任何支持Java的平台上运行,这得益于Java虚拟机(JVM)的跨平台特性。JavaResearch项目正是基于这个强大的平台,深入解析了Java语言的关键组件,如类加载器、垃圾收集机制、多...
这里提到的`concurrent-1.3.4-sources.jar`是一个特定版本的Java并发库源代码包,它包含了Java并发编程的核心组件和工具,对理解并发编程有着重要的参考价值。这个版本是1.3.4,虽然相比现代的Java版本可能有些过时...
在业务代码中,根据实际需求,通过`DataSourceContextHolder`设置当前数据源,Spring会自动根据设置选择对应的数据源进行操作。例如: ```java public void someServiceMethod() { DataSourceContextHolder....
6. **核心代码解析** - `DataSourceConfig`:这里会创建多个`DataSource`实例,例如`primaryDataSource`和`secondaryDataSource`,并可能使用`@ConfigurationProperties`进行属性绑定。 - `...
### 基于注解的Spring多数据源配置与使用详解 #### 一、引言 在企业级应用开发中,经常会遇到需要从多个数据库拉取数据的情况,比如进行跨库查询、定时任务中的数据分析及报表统计等。Spring框架作为Java开发领域的...
- 在业务代码中,可以通过设置ThreadLocal变量或者利用AOP拦截器来实现数据源的切换。 6. **注意事项** - 为了避免数据源混乱,确保在使用不同数据源的Service或DAO层类前,正确地设置当前线程的数据源。 - 在多...
结合Faucet.java文件,这可能是某个特定功能或算法的实现,具体细节需要查看源代码才能进一步解析。 总之,实现Java代码的“飞流直下”不仅需要对语言特性有深入理解,还需要掌握各种优化策略,结合实际应用环境,...
在业务代码中,可以通过ThreadLocal来保存当前线程所使用的数据源信息,然后在执行SQL时,动态数据源会根据这个信息选择正确的目标数据源。 ```java public class DataSourceContextHolder { private static final...
本资源提供了详细的Java多线程设计模式详解,包括PDF文档和源代码,使得学习过程更加直观和实践性强。 首先,我们要理解什么是多线程。在单线程环境下,程序执行是顺序的,而在多线程环境中,多个任务可以同时执行...
通过这些源代码,我们可以逐一解析和学习以下关键知识点: 1. **基础语法**:包括变量、数据类型、运算符、流程控制(if-else、switch、for、while等)、方法定义与调用、类和对象的创建等。这些是Java编程的基础,...
本文将详细解析如何利用`AbstractRoutingDataSource`来解决多数据源的问题。 `AbstractRoutingDataSource`是Spring框架中的一个抽象类,它是基于路由的数据源,可以根据当前的上下文环境(比如当前线程的信息)动态...
本文将深入探讨Spring Boot如何实现动态数据源,并基于提供的"springboot动态数据源.zip"压缩包文件进行解析。 首先,Spring Boot通过`@EnableConfigurationProperties`注解和`DataSourceProperties`类来支持数据源...
传统的方法中,会在配置文件中配置多个数据源,然后在DAO层代码中硬编码指定这些数据源,但这种方法存在明显的缺点,比如需要修改源码才能增加新的数据源,这显然违背了软件设计的开闭原则。为了解决这些问题,我们...
Spring 动态数据源实现读写分离详解 Spring 框架为我们提供了强大的数据源管理机制,通过动态数据源实现读写分离,可以大大提高系统的性能和可扩展性。本文将详细介绍 Spring 动态数据源实现读写分离的过程,包括...