定义:
ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的。ThreadLocal为每个线程都创建了一个副本,存的是自己,那么每个线程可以访问自己内部的副本变量。
ThreadLocal是用空间换取时间,synchronized关键字是用时间换空间。
ThreadLocal操作值的时候是取得当前线程的ThreadLocalMap对象,然后把值设置到了这个对象中,这样对于不同的线程得到的就是不同的ThreadLocalMap,那么向其中保存值或者修改值都只是会影响到当前线程,这样就保证了线程安全。
使用:
由于Thread中包含变量ThreadLocalMap,因此ThreadLocalMap与Thread的生命周期是一样长,如果都没有手动删除对应key,都会导致内存泄漏。
但是使用弱引用可以多一层保障:弱引用ThreadLocal不会内存泄漏,对应的value在下一次ThreadLocalMap调用set(),get(),remove()的时候会被清除。
因此,ThreadLocal内存泄漏的根源是:由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应key就会导致内存泄漏,而不是因为弱引用。
ThreadLocal正确的使用方法:
每次使用完ThreadLocal都调用它的remove()方法清除数据
将ThreadLocal变量定义成private static,这样就一直存在ThreadLocal的强引用,也就能保证任何时候都能通过ThreadLocal的弱引用访问到Entry的value值,进而清除掉 。
使用场景:
1、在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。
2、线程间数据隔离,【你访问你的,我访问我的,不会相互干扰】
3、进行事务操作,用于存储线程事务信息。
4、数据库连接,Session会话管理。
5、MDC链路追踪。
如何解决线程池中的值传递功能?(ThreadLocal,InheritableThreadLocal ,TransmittableThreadLocal区别)
InheritableThreadLocal 继承 ThreadLocal,主要用于子线程创建时,需要自动继承父线程的ThreadLocal变量,方便必要信息的进一步传递。
由于InheritableThreadLocal是在异步子线程初始化时进行的设置,而线程只会初始化一次,就会导致子线程中的ThreadLocal一直是同一个。
开发中,一般会用池化的技术来管理多个线程,即会用到线程池。在线程池中,核心线程一般来说是不会死的,他们会被反反复复使用。用InheritableThreadLocal的问题在于,threadLocal只在子线程初始化的时候进行了传递,当这个子线程完成了第一个任务,随后处理其他请求时,这个子线程中的threadLocal却还一直是第一个请求时设置的那个threadLocal,就会导致出错。
在遇到线程池等会池化复用线程的执行组件情况下,就需要通过TransmittableThreadLocal类来实现线程值传递。
MDC链路追踪如何使用ThreadLocal?
异步服务的统一API,例如:文章来源:https://www.toymoban.com/news/detail-669435.html
@Override
@Async
public <T> void execute(Map<String, String> logContext, Consumer<T> consumer, T t) {
this.dealLogContext(logContext);
LOGGER.debug("发起异步调用,设置线程日志上下文");
try {
LOGGER.debug("调用函数");
consumer.accept(t);
LOGGER.debug("发起异步调用完成");
} catch (Exception e) {
LOGGER.warn(e, "发起异步调用异常");
} finally {
MDC.clear();
}
}
private void dealLogContext(Map<String, String> logContext) {
MDC.clear();
if (logContext == null) {
logContext = new HashMap<>();
logContext.put("traceId", Logger.genTraceId());
}
MDC.setContextMap(logContext);
}
对于消息队列MQ,则需要通过传参的方式,在消费者端,手动给当前线程ThreadLocal赋值。文章来源地址https://www.toymoban.com/news/detail-669435.html
到了这里,关于线程安全—ThreadLocal的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!