`

读ThreadLocal源代码

阅读更多
//可以存取线程局部变量

//先看构造函数
public ThreadLocal() {
    }

//设置值
public void set(T value) {
        Thread t = Thread.currentThread();
	//这个Map以this为key
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

//继承了WeakReference说明这个key是自动回收的
static class ThreadLocalMap {
        static class Entry extends WeakReference<ThreadLocal> {
           
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }

private void set(ThreadLocal key, Object value) {

            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);

            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                ThreadLocal k = e.get();

                if (k == key) {
                    e.value = value;
                    return;
                }

                if (k == null) {
                    replaceStaleEntry(key, value, i);
                    return;
                }
            }

            tab[i] = new Entry(key, value);
            int sz = ++size;
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }

//获取保存的值
public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);

        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
	    //有值则返回
            if (e != null)
                return (T)e.value;
        }
	//返回初始化的值
        return setInitialValue();
    }

//设置初始化的值
private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }

//覆盖这个方法获取初始值
protected T initialValue() {
        return null;
    }

//删除值
 public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }


/**
总结:ThreadLocal主要用于传递变量。如果要设置初始化的值可以直接覆盖initialValue()方法即可。
其原理是:将值存在一个ThreadLocalMap中。以自身为key,值为value。这个map继承了WeakReference。
说明其对于key是弱引用(相当于WeakHashMap)。
*/

分享到:
评论

相关推荐

    spring 动态多数据源配置代码

    通过自定义`CurrentDataSourceHolder`类或使用`ThreadLocal`来保存当前线程的数据源信息。在需要切换数据源的地方,更新这个信息,`AbstractRoutingDataSource`会自动识别并选择正确数据源。 6. **代码示例**: ...

    sqlSessionFactory方式-多数据源的案例代码

    - **数据源切换逻辑**:在业务逻辑中,可以通过设置ThreadLocal变量或者利用AOP(面向切面编程)来切换数据源。例如,读操作使用读库,写操作使用写库。 - **Mapper配置**:每个数据源的Mapper配置文件需要独立,...

    spring多数据源

    6. **在代码中切换数据源**:在业务代码中,可以通过ThreadLocal或其他方式设置当前数据源的标识,使得在执行SQL操作时,Spring能够根据设定自动选择正确的数据源。 7. **读写分离**:多数据源的一个常见应用场景是...

    spring 动态切换数据源

    - 在业务代码中,可以通过设置`DynamicDSHolder`中的数据源key来切换数据源。例如,在服务开始前,设置`DynamicDSHolder.setDsKey("primary")`,则后续的数据操作将使用`primaryDataSource`。 6. **AOP切面** - ...

    mybaties切换数据源.rar

    5. **切换策略**:在实际项目中,数据源的切换策略可能会更复杂,例如通过AOP拦截器来判断请求类型(读/写)并设置当前数据源的key,或者使用ThreadLocal来存储数据源key等。 通过以上步骤,我们可以实现MyBatis的...

    springboot+mybatis配置多数据源,通过注解自动切换

    - 在`@Around`通知中,根据方法上的`@SwitchDataSource`注解的值,动态改变`ThreadLocal`中的数据源,使得后续的数据库操作使用指定的数据源。 3. **读写分离** - 读写分离的基本思想是:主库负责写操作,从库...

    spring boot动态切换多数据源

    - `DynamicDataSourceRouter`:通常会有一个`Map`存储所有的数据源,并通过`ThreadLocal`或`RequestContextHolder`来保存当前选择的数据源。 - 在`@Service`或`@Repository`类中,使用`@Autowired`注入`DataSource...

    mybatisplus-多数据源demo

    创建一个自定义的`ThreadLocal`变量来保存当前线程所使用的数据源信息。 - 创建一个切面,拦截特定的注解,如`@DS`(代表Data Source),根据注解的值来切换数据源。 3. **MyBatisPlus的多数据源整合**: - ...

    Spring配置动态数据源实现读写分离的方法

    在Spring框架中,实现数据库的读写分离是提高系统性能的一种常见策略,它可以将读操作和写操作分散到不同的数据源上,减轻主数据库的压力。本文将详细介绍如何利用Spring配置动态数据源来实现这一功能。 首先,我们...

    spring读写分离

    标题中的“Spring读写分离”指的是在基于Spring框架的应用中实现数据库的读写操作分离,以提高...对于标签中提到的“源码”,深入研究Spring和MyBatis的源代码可以帮助我们理解其内部工作原理,提升开发和调试能力。

    使用Spring实现读写分离(MySQL实现主从复制)

    2. **使用ThreadLocal确保线程安全**:由于数据源配置通常是单例模式,为保证线程安全,可以借助`ThreadLocal`类。 3. **实现AOP切面**:编写一个AOP切面,在业务方法调用前后分别设置和清除数据源标识。 #### 示例...

    JavaAnnotation实例.docx

    Java Annotation 是一种元数据,它允许我们在源代码中嵌入信息,这些信息可以被编译器或运行时环境用于处理代码。Annotation 不是代码本身,但可以影响代码的行为或提供编译时和运行时的元信息。它们在 Java 中的...

    良葛格java jdk 5.0学习笔记

    注解为元数据提供了一种机制,使得程序员可以在源代码中添加声明性信息,这些信息可以在编译时或运行时被处理。注解广泛应用于依赖注入、代码生成、验证等领域。 增强的for循环(也称为foreach循环)是JDK 5.0的另...

    Spring+MyBatis实现数据读写分离的实例代码

    数据读写分离是数据库优化的重要策略,它将高并发的读操作和低频的写操作分配到不同的数据源上,以提高系统的性能和可用性。Spring和MyBatis框架结合,可以通过AOP(面向切面编程)和自定义插件来实现这一功能。 1....

    DynamicSoures.zip

    5. **切换数据源**:在业务逻辑中,我们可以通过AOP或ThreadLocal等方式来实现数据源的动态切换。一种常见做法是创建一个事务管理器,根据事务的类型(如读/写)选择合适的数据源。 ```java @Configuration @...

    spring mybatis多数据源实例详解

    - 在业务代码中,可以通过设置ThreadLocal变量或者利用AOP拦截器来实现数据源的切换。 6. **注意事项** - 为了避免数据源混乱,确保在使用不同数据源的Service或DAO层类前,正确地设置当前线程的数据源。 - 在多...

    Bat面试题汇总&详解

    源代码阅读能力体现了开发者深入理解技术的能力。例如,阅读`HashMap`源码可以理解其内部实现,包括扩容策略、碰撞处理等。 以上是针对BAT面试中涉及的Java多线程、JVM、Java扩展、Spring、中间件、数据库和Redis等...

    IT互联网名企经典面试题汇总:Java篇1

    17. **源码阅读**:阅读和理解开源框架的源代码,如Spring、Hibernate等,有助于深入理解其工作原理。 18. **Redis**:内存数据存储系统,常用于缓存、消息队列等场景,掌握其数据类型、持久化策略、主从复制和...

    springBoot配置多数据库

    创建一个ThreadLocal变量来保存当前线程所使用的数据源,然后在需要切换数据源的方法上添加自定义注解,AOP切面会在方法执行前后进行数据源的切换。 3. **事务管理** - 多数据源事务管理是较复杂的一部分。Spring...

    Spring boot实现数据库读写分离的方法

    `DbContextHolder`类是一个线程安全的工具类,它使用`ThreadLocal`存储当前线程的数据库类型。通过`setDbType()`、`getDbType()`和`clearDbType()`方法,可以在执行查询前后动态切换数据源。例如,在执行写操作时,...

Global site tag (gtag.js) - Google Analytics