java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > ThreadLocal应用场景及问题

Java多线程中的ThreadLocal应用场景及问题解读

作者:竹下星空

这篇文章主要介绍了Java多线程中的ThreadLocal应用场景及问题解读,ThreadLocal这个类在多线程并发中主要的使用场景是什么呢,我们都知道多线程并发问题实际就是多个线程对公共资源访问和修改问题,需要的朋友可以参考下

ThreadLocal的应用场景

ThreadLocal这个类在多线程并发中主要的使用场景是什么呢,我们都知道多线程并发问题实际就是多个线程对公共资源访问和修改问题,通过我们之前的分析:

如果我们的公共资源只是一个int或boolean等基本数据类型的变量,而且只是简单的赋值或查询操作,典型的场景就是各种开关和一些标识位操作,那么我们使用volatile保证变量的可见性就可以了

如果我们的操作是一个对int的累加操作或其他一些基础类型的累加操作,那么我们使用cas实现的atomic类可以实现简单的原子性操作

如果我们的操作是多个共享资源或更加复杂的原子性操作,那么我们使用synchronized或lock家族类保证操作的原子性

那么ThreadLocal到底补上了多线程并发中哪种场景的操作?

ThreadLocal实际就是处理了一个资源虽然是公共资源,但每个线程都自己独有一份且不需要知道这个资源在其他线程中的状态,各个线程自己本地的公共资源就好了。

所以这个资源只跟线程本身有关,随着线程的存在而存在,随着线程的消亡而消亡。比较典型的场景就是每个web请求request对象所带的信息(ip,token,请求参数),所以在好多情况下都会用ThreadLocal保存request。

ThreadLocal是怎么做到把资源绑定到相应线程上的

public void set(T value) {
Thread t = Thread.currentThread();
//拿到当前线程,然后通过当前线程获取他的成员变量threadLocals,threadLocals实际就是一个map
ThreadLocalMap map = getMap(t);
//当线程的threadLocals不是null时,直接把当前ThreadLocal对象作为key,设置的值作为value放入map中
if (map != null)
map.set(this, value);
else
//如果threadLocals是null时,直接new ThreadLocalMap给当前线程的threadLocals成员变量
createMap(t, value);
}

总结

那为什么说threadLocal可能导致内存泄漏呢

当前线程长时间没执行完而此时又发生GC,而线程成员变量threadLocals指向的ThreadLocalMap是一个map,key是threadLocal,value是set的值,而key是一个弱引用,在没有其他对象引用的情况下在gc会被回收,而value是强引用,只要线程不消亡就不会被回收,所以就会造成key为null而value不为null的情况,此时我们已经无法拿到这个value,这就造成了内存泄漏(系统没用的对象占用了内存,而gc又无法回收)。所以在使用threadLocal时一定记得使用finnaly调用remove方法

很多情况下我们都会使用线程池来处理请求和一些业务。线程池里面的线程都是重复使用的,如果在上一次处理业务时没有remove,那么这次从theadLocal拿数据时就会拿到上次请求的数据,这就导致了数据混乱

到此这篇关于Java多线程中的ThreadLocal应用场景及问题解读的文章就介绍到这了,更多相关ThreadLocal应用场景及问题内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文