`

InheritableThreadLocal 源码分析

阅读更多

/*
* Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/

package com.hanlin.fadp;
import java.lang.ref.*;

/**
* This class extends <tt>ThreadLocal</tt> to provide inheritance of values
* from parent thread to child thread: when a child thread is created, the
* child receives initial values for all inheritable thread-local variables
* for which the parent has values.  Normally the child's values will be
* identical to the parent's; however, the child's value can be made an
* arbitrary function of the parent's by overriding the <tt>childValue</tt>
* method in this class.
*
* <p>Inheritable thread-local variables are used in preference to
* ordinary thread-local variables when the per-thread-attribute being
* maintained in the variable (e.g., User ID, Transaction ID) must be
* automatically transmitted to any child threads that are created.
*
* @author  Josh Bloch and Doug Lea
* @see     ThreadLocal
* @since   1.2
*/

public class InheritableThreadLocal<T> extends ThreadLocal<T> {
    /**
     * 这个方法留给子类实现
     *
     * @param parentValue the parent thread's value
     * @return the child thread's initial value
     */
    protected T childValue(T parentValue) {
        return parentValue;
    }


    /**
     * 重写getMap方法,返回的是Thread的inheritableThreadLocals引用
     *
     * @param t the current thread
     */
    ThreadLocalMap getMap(Thread t) {
       return t.inheritableThreadLocals;
    }


    /**
     * 重写createMap方法,构造的ThreadLocalMap会传给Thread的inheritableThreadLocals 变量
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the table.
     * @param map the map to store.
     */
   void createMap(Thread t, T firstValue) {
        t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
    }

}


它是如何实现父子线程间 ThreadLocal 传递的了?


首先,重写了 getMap 和 createMap 方法,因为 ThreadLocal 在执行 set 方法或者 get 方法的时候,会用到.




是不是发现了啥?这里使用的是 inheritableThreadLocals,而不再是 ThreadLocal 中的 threadLocals.

再看 Thread 类的 init 方法:

private void init(ThreadGroup g, Runnable target, String name,
                  long stackSize, AccessControlContext acc) {
    if (name == null) {
        throw new NullPointerException("name cannot be null");
    }

    this.name = name.toCharArray();

    Thread parent = currentThread();
    SecurityManager security = System.getSecurityManager();
    if (g == null) {
        /* Determine if it's an applet or not */

        /* If there is a security manager, ask the security manager
           what to do. */
        if (security != null) {
            g = security.getThreadGroup();
        }

        /* If the security doesn't have a strong opinion of the matter
           use the parent thread group. */
        if (g == null) {
            g = parent.getThreadGroup();
        }
    }

    /* checkAccess regardless of whether or not threadgroup is
       explicitly passed in. */
    g.checkAccess();

    /*
     * Do we have the required permissions?
     */
    if (security != null) {
        if (isCCLOverridden(getClass())) {
            security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
        }
    }

    g.addUnstarted();

    this.group = g;
    this.daemon = parent.isDaemon();
    this.priority = parent.getPriority();
    if (security == null || isCCLOverridden(parent.getClass()))
        this.contextClassLoader = parent.getContextClassLoader();
    else
        this.contextClassLoader = parent.contextClassLoader;
    this.inheritedAccessControlContext =
            acc != null ? acc : AccessController.getContext();
    this.target = target;
    setPriority(priority);
    // 这里 inheritableThreadLocals 将不再为空,ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); 语句会把父类中的 ThreadLocal 中的值拷贝一份到子类中.
    if (parent.inheritableThreadLocals != null)
        this.inheritableThreadLocals =
            ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

    /* Stash the specified stack size in case the VM cares */
    this.stackSize = stackSize;

    /* Set thread ID */
    tid = nextThreadID();
}


说明:父子线程 ThreadLocal 在拷贝的时候,拷贝的是引用,也就是说如果父线程修改了 ThreadLocal 中的某个对象,那么子线程中 ThreadLocal 的值也会跟着变.


理论分析:




测试:
package com.hanlin.fadp;

public class InheritableThreadLocalTest {


    static class Person{
        String name;

        public Person(String name) {
            this.name = name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    public static ThreadLocal<Person> inheritableThreadLocal = new InheritableThreadLocal<Person>();

    static CountDownLatch latch = new CountDownLatch(1);

    public static void main(String args[]) throws InterruptedException {

        Person tom = new Person("tom");
        inheritableThreadLocal.set(tom);

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {

                    Person p = inheritableThreadLocal.get();
                    p.setName("sdsds");

                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("子线程<InheritableThreadLocal>:" + inheritableThreadLocal.get());
                latch.countDown();
            }
        }, "AAAAA").start();
        System.out.println("父线程<InheritableThreadLocal>:" + inheritableThreadLocal.get());

        Thread.sleep(1000);

//        Person p = inheritableThreadLocal.get();
//        p.setName("sdsds");
//        inheritableThreadLocal.set(p);

        latch.await();

        System.out.println("父线程<InheritableThreadLocal>:" + inheritableThreadLocal.get());
    }
}


结果:



0
0
分享到:
评论

相关推荐

    Android 详解ThreadLocal及InheritableThreadLocal

    在Android SDK 23的源码中,ThreadLocal的实现可能与Java标准库有所不同,这主要是为了适应Android平台的优化和限制。例如,Android可能使用了特定的内存管理策略或者线程局部存储实现。 总的来说,ThreadLocal和...

    InheritableThreadLocal & ThreadLocal

    《InheritableThreadLocal & ThreadLocal 深度解析》 在Java编程中,线程局部变量(ThreadLocal)和可继承线程局部变量(InheritableThreadLocal)是两种非常重要的工具,它们允许我们在多线程环境中创建独立于线程...

    ThreadLocal、InheritableThreadLocal详解

    ThreadLocal和InheritableThreadLocal是Java中处理线程局部变量的两个类,它们主要用于解决多线程环境下的数据隔离问题。线程安全是并发编程中的核心问题之一,当多个线程访问同一份共享资源时,可能会导致数据不...

    java多线程编程之InheritableThreadLocal

    * InheritableThreadLocal 的实现原理和源码分析 * InheritableThreadLocal 与 ThreadLocal 的区别 * 使用 InheritableThreadLocal 需要注意的线程安全问题 * InheritableThreadLocal 在多线程编程中的应用场景和...

    Java_为frameworkmiddleware提供了一个增强的InheritableThreadLocal,即使使.zip

    Java中的`InheritableThreadLocal`是线程局部变量的一个扩展,它允许子线程继承父线程中`InheritableThreadLocal`实例的值。这个特性在开发框架和中间件时尤其有用,因为它可以方便地传递上下文信息,如会话状态、...

    ThreadLocal垮线程池传递数据解决方案.docx

    2 InheritableThreadLocal 的局限性:InheritableThreadLocal 仅限于父线程给子线程来传递数据,不能解决跨线程池之间的数据传递问题。 3 TransmittableThreadLocal 的实现原理:TransmittableThreadLocal 是基于...

    java1.8源码-jdk1.8.0_111:JDK1.8源码注释

    InheritableThreadLocal跟ThreadLocal差不多,关键点在Thread#init方法中会对Thread中的实例变量inheritableThreadLocals进行赋值操作,将父线程的本地变量复制到子线程中 首先通过ServiceLoader.load方法生成一个...

    Java进阶知识点汇总.pdf

    ### Java进阶知识点详解 #### 第一章:基本语法 ##### 关键字 - **static**:用于定义...以上是对Java进阶知识点的详细解析,覆盖了基本语法、JDK源码分析等多个方面,有助于深入理解Java语言的核心机制及高级特性。

    transfertable-thread-local::pushpin:TransmittableThreadLocal(TTL),缺少框架中间件的Java:trade_mark:std lib(简单和0依赖),提供了增强的InheritableThreadLocal,即使使用线程池组件也可以在线程之间传输值

    :pushpin: TransmittableThreadLocal(TTL) :pushpin: | :open_book:中文文档 :wrench:功能 :backhand_index_pointing_right:在使用线程池等会池化复用线程的执行组件情况下,提供ThreadLocal值的...

    JAVA八股文Java基础-供大家学习研究参考

    5. InheritableThreadLocal作用和实现方式 ? 6. InheritableThreadLocal所带来的问题? 7. 如何解决线程池异步值传递问题 ( transmittable-thread-local)? HashMap ConcurrentHashMap相关 9. HashMap为什么线程...

    Java 20 新功能介绍.pdf

    Scoped Value 解决了在线程之间共享变量的问题,ThreadLocal 和 InheritableThreadLocal 都有其缺陷。ThreadLocal 需要手动清理,且变量不能被子线程继承;InheritableThreadLocal 可以共享信息,但是数据会拷贝多份...

    Spring Security tutorial 学习笔记(一)

    `SecurityContextHolder` 类提供了获取和设置安全上下文的方法,通常通过 `SecurityContextHolder.MODE_INHERITABLETHREADLOCAL` 模式在多线程环境中传播。 **6. ** **用户详情服务(UserDetailsService)** 用户...

    使用acegi控制用户权限实例

    5. **启动安全上下文**:在Spring的初始化代码中,调用`SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);`来激活安全上下文。 6. **测试和调试**:使用模拟用户或真实...

    Spring Cloud体系实现标签路由的方法示例

    `RequestZoneLabelContext`使用`InheritableThreadLocal`来保存线程上下文,这样即使在请求处理过程中产生了新的线程,这些线程也能继承到标签信息。当请求结束时,会清除`RequestZoneLabelContext`中的信息,防止...

    java_lang包详解.pdf

    在Java 2版本中,java.lang包引入了一些新的类和接口,例如InheritableThreadLocal、RuntimePermission等,以增强多线程特性和安全控制。同时,一些过时的方法也被标记出来,虽然仍可供老程序使用,但不建议在新代码...

    JAVA面试题.docx

    **其他并发工具类与锁原理**:这部分内容涉及ThreadLocal的工作原理、InheritableThreadLocal如何传递线程局部变量、CyclicBarrier和CountDownLatch的区别与用法、Semaphore信号量机制、CopyOnWriteArrayList如何...

Global site tag (gtag.js) - Google Analytics