ThreadLocal原理与使用

傷城~ 2023-10-12 21:12 28阅读 0赞

文章目录

  • 实现原理
    • ThreadLocal的存值操作
    • ThreadLocal的取值操作
  • 使用场景

ThreadLocal是Java中的一个线程本地存储类,它可以用于将某个对象绑定到当前线程上。这样,在同一个线程中不同方法都可以访问到这个对象,而不需要将对象作为参数传递或者使用全局变量。

实现原理

ThreadLocal内部使用了一个ThreadLocalMap类来保存每个线程的值。ThreadLocalMap是一个使用线性探测法解决哈希冲突的哈希表,它的键值是ThreadLocal对象,值是对应线程中保存的对象。

当使用ThreadLocal.set方法设置一个值时,ThreadLocal首先获取当前线程,然后获取当前线程对应的ThreadLocalMap对象。ThreadLocalMap的getEntry方法使用ThreadLocal对象作为参数,返回当前线程中关联的Entry对象。如果Entry不存在,ThreadLocalMap就会使用ThreadLocal对象创建一个新的Entry并放到当前线程的ThreadLocalMap中。然后将需要保存的对象保存到Entry中。

当使用ThreadLocal.get方法获取值时,ThreadLocal还是会获取当前线程和对应的ThreadLocalMap对象,然后使用ThreadLocal对象作为参数调用ThreadLocalMap中的getEntry方法获取Entry。如果Entry不存在,ThreadLocalMap会使用ThreadLocal对象创建一个新的Entry并放到当前线程的ThreadLocalMap中。然后将新创建的Entry返回,Entry的getValue方法就可以返回之前保存的对象了。

ThreadLocal的存值操作

  1. public void set(T value) {
  2. Thread t = Thread.currentThread();
  3. ThreadLocalMap map = getMap(t);
  4. if (map != null)
  5. map.set(this, value);
  6. else
  7. createMap(t, value);
  8. }
  9. ThreadLocalMap getMap(Thread t) {
  10. return t.threadLocals;
  11. }
  12. void createMap(Thread t, T firstValue) {
  13. t.threadLocals = new ThreadLocalMap(this, firstValue);
  14. }

ThreadLocal的取值操作

  1. public T get() {
  2. Thread t = Thread.currentThread();
  3. ThreadLocalMap map = getMap(t);
  4. if (map != null) {
  5. ThreadLocalMap.Entry e = map.getEntry(this);
  6. if (e != null) {
  7. @SuppressWarnings("unchecked")
  8. T result = (T)e.value;
  9. return result;
  10. }
  11. }
  12. return setInitialValue();
  13. }

使用场景

ThreadLocal通常用于下列情况:

  1. 将一个普通变量保存到ThreadLocal中,使其在当前线程中随时可用,从而避免多次传参的麻烦。
  2. 将有状态的组件保存到ThreadLocal中,使得它们在第二次使用时可以避免重复初始化,从而提高性能和效率。
  3. 实现线程安全的单例模式,通过ThreadLocal来保证每个线程内只有一个实例。

ThreadLocal使用需要注意的点

  1. 内存泄漏:ThreadLocalMap中的Entry对象是弱引用,只有在当前线程存活期内且该线程的ThreadLocalMap存在时,则Entry对象才不会被回收。如果ThreadLocal没有及时地被回收,会导致Entry对象无法回收,进而导致内存泄漏问题。
  2. 释放资源:使用ThreadLocal时需要手动调用remove方法来清除保存在线程中的对象,以免造成资源的浪费。
  3. 线程不安全:ThreadLocal只是用来保存本线程中的数据,因此在并发的情况下,每个线程都有自己的变量副本,因此不会发生线程安全的问题。但是,如果多个线程共用一个ThreadLocal,那么仍然会出现线程安全的问题。

发表评论

表情:
评论列表 (有 0 条评论,28人围观)

还没有评论,来说两句吧...

相关阅读