Java ThreadLocal 应用

[b]一、需求介绍[/b]
由于项目需要在同一进程不同方法内获取到上下文内容,而在同一线程父方法可以获取到上下文内容,子方法由不同的项目组提供和开发,然后以jar包的方式打包,这时候问题就出现了,父方法的上下文内容如何可以提供给子方法,并在子方法中获取到对应线程的上下文内容?

注:每个线程的上下文内容是不同的,父类只提供集成容器,具体方法的实现由不同的项目组和部门编写

[b]二、解决思路[/b]
应用Java 提供的ThreadLocal

首先查看下TheadLocal提供的方法
T get()
返回此线程局部变量的当前线程副本中的值。
protected T initialValue()
返回此线程局部变量的当前线程的初始值。
void remove()
移除此线程局部变量的值。
void set(T value)
将此线程局部变量的当前线程副本中的值设置为指定值。


2.1、get 方法:
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();
}

说明:
1、首先获取当前线程
2、获取当前线程的ThreadLocalMap即threadLocals
getMap(Thread t)源码为:
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
3、如果当前线程存在threadLocals则根据当前的ThreadLocal获取threadLocals的值.(threadLocals其实就是一Map)
4、如果当前线程的ThreadLocalMap为null,则执行方法setInitialValue()

可以看的出是获取Thread的threadLocals
Thread中源码为如下:
ThreadLocal.ThreadLocalMap threadLocals = null;

2.2、set 方法
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
源码说明:
1、首先获取当前线程
2、获取当前线程ThreadLocalMap
3、如果ThreadLocalMap不为null set(ThreadLocal,value)
4、如果为null createMap(Thread,value);

备注:这里可以看出不为null时,set的内容为key:ThreadLocal,value:value,也就是说每个线程都有一个ThreadLocalMap这个map内存放得内容为ThreadLocal,value

接下来在看下createMap源码
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}

备注:该方法为当前线程的内部变量threadLocals进行了赋值操作,而ThreadLocalMap为ThreadLocal的内部类。new ThreadLocalMap(this, firstValue) 内部进行的操作也是为当前线程的threadLocals变量进行了set操作,key为当前的ThreadLocal,value为传入的firstValue

2.3、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;
}

该方法返回null,并会创建当前线程的threadLocals

综上:应用ThreadLocal在线程中进行上下文同步时,要保持一致的ThreadLocal。当多线程应用线程池时,要保证线程池中相同的线程每次拿到得ThreadLocal要不相同,否则会出现问题。


[b]回到问题的开始,解决该问题的方案为[/b]
1、创建一个单例类(ex:ThreadLocalTest)保证线程上下文拿到得ThreadLocal都一致
2、父类提供给子类可以获取单例类ThreadLocalTest的方法。(要是子类分别由不同的部门、项目组以jar的方式提供时,负责父类服务的可以给项目组提供一个通用的jar文件)
3、在调用父类多线程入口时获取ThreadLocalTest单例,set(上下文内容)
4、子类在方法内获取ThreadLocalTest单例调用get()方法获取当前线程的value即为上下文内容
5、父类调用子方法后执行ThreadLocalTest.remove()操作

public class ThreadLocalTest<T> {
private static ThreadLocal local = new ThreadLocal();
private static ThreadLocalTest threadlocaltest = null;

public synchronized ThreadLocalTest getInitialize(){
if(threadlocaltest == null){
threadlocaltest = new ThreadLocalTest<T>();
}
return threadlocaltest;
}

public T get(){
return (T) local.get();
}

public void set(T t){
local.set(t);
}

public void remove(){
local.remove();
}
}


[b]后记:[/b]
很多人问我,在父类中既然可以获取到上下文那直接传给子类方法就行了啊。注意前提说的是父类只负责提供一个容器,具体的实现由不同的部门和项目组编写
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值