ThreadLocal如何在父子线程及线程池中传递

作者:神秘网友 发布时间:2020-09-22 11:13:22

ThreadLocal如何在父子线程及线程池中传递

ThreadLocal如何在父子线程及线程池中传递

目录

 

子线程如何获取父线程的本地变量?

case

解决问题

子线程获取父线程ThreadLocal值

InheritableThreadLocal

问题


子线程如何获取父线程的本地变量?

子线程提交任务时,获取父线程ThreadLocal的值

case

之前遇到过多个线程都需要使用SimpleDataFormat对象来做日期格式化,当时第一时间想到的就是定义一个static的SimpleDataFormat让多线程共享。但是很显然这样做就是在写bug,因为SimpleDataFormat不是线程安全的,势必会出现并发问题。

解决问题

解决并发问题有很多种

  • 悲观锁:使用简单,但锁粒度比较大,对读和写一视同仁
  • 乐观锁:写少读多
  • 线程本地变量:提供线程内部存储变量能力,线程私有,不会出现共享问题
  • 等等...

子线程获取父线程ThreadLocal值

InheritableThreadLocal

jdk提供了InheritableThreadLocal

ThreadLocal如何在父子线程及线程池中传递

InheritableThreadLocal继承自ThreadLocal

 ThreadLocal如何在父子线程及线程池中传递

 1.当ThreadLocal使用方法存储的是基本变量时

public static ThreadLocal<Integer> threadLocal = new InheritableThreadLocal<>();

2.如果是引用变量

继续使用InheritableThreadLocal,父子线程就又存在多线程的问题

原理不做真如分析,跟InheritableThreadLocal的这个方法有关

由于直接返回入参,没有进行深拷贝,所以存在父子线程共享变量的问题

 /**
     * Computes the child's initial value for this inheritable thread-local
     * variable as a function of the parent's value at the time the child
     * thread is created.  This method is called from within the parent
     * thread before the child is started.
     * <p>
     * This method merely returns its input argument, and should be overridden
     * if a different behavior is desired.
     *
     * @param parentValue the parent thread's value
     * @return the child thread's initial value
     */
    protected T childValue(T parentValue) {
        return parentValue;
    }

这个时候我们就需要区重写这个方法达到深拷贝的目的(采用序列化/反序列化的方法)

public class MyInheritableThreadLocal<T> extends InheritableThreadLocal<T>{
    @Override
    protected T childValue(T parentValue){
        String s = JSONObject.toJSONString(parentValue);
        return (T)JSONObject.parseObject(s,parentValue.getClass());
    }
}

问题

不管是InheritableThreadLocal还是实现MyInheritableThreadLocal都是现成创建之初就已经创建好的。但如果是线程池的场景,是维持了一个若干线程的,有可能创建好了就不会再重新创建了,也就是线程复用。这个时候InheritableThreadLocal的值被改变了,要是再次有任务提交。那么使用的共享值就不再是拷贝自父线程的值了,也无法再次获取父线程的本地变量。

解决方法

TransmittableThreadLocal是阿里开源用来解决这一问题的扩展,原理就不想写的太深了,以后有机会继续研究

public class MyInheritableThreadLocal<T> extends TransmittableThreadLocal<T>{
    @Override
    protected T copy(T parentValue){
        String s = JSONObject.toJSONString(parentValue);
        return (T)JSONObject.parseObject(s,parentValue.getClass());
    }
}

 

ThreadLocal如何在父子线程及线程池中传递相关教程

  1. 如何在IIS67中部署ASP.NET网站
  2. ThreadLocal原理分析及内存泄漏解决方法
  3. linux 文件加密_如何在Linux上使用gocryptfs加密文件
  4. 如何在 Linux 终端中连接 WiFi? | Linux 中国
  5. 从零开始实现ASP.NET Core MVC的插件式开发(三) - 如何在运行时
  6. 如何在eclipse将web项目打成war包并导入阿里云ECS服务器CentOS7
  7. 如何在小程序中开通支付功能
  8. Mac小技巧 如何在 Mac 上创建加密文件夹(1)