ThreadLocal的实现

0.简介:创建线程局部变量的类

使用ThreadLocal创建的变量只能被当前线程访问,其他线程则无法访问和修改。

  • 内部类ThreadLocalMap实现,key是变量,value是所在的线程。

用法如下:

private void testThreadLocal() {
    Thread t = new Thread() {
        ThreadLocal<String> mStringThreadLocal = new ThreadLocal<>();

        @Override
        public void run() {
            super.run();
            mStringThreadLocal.set("localValue"); // 设置值
            mStringThreadLocal.get(); // 获取值
        }
    };

    t.start();
}

1.如何实现:依靠内部类ThreadLocalMap

set是如何实现的?

  • 首先获取当前线程
  • 利用当前线程作为句柄获取一个ThreadLocalMap的对象
  • 如果ThreadLocalMap对象不为空,则设置值;否则创建这个ThreadLocalMap对象并设置值
public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

下面是一个利用Thread对象作为句柄获取ThreadLocalMap对象的代码:

ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

可以看出一个Thread实例就有一个ThreadLocalMap对象。

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();
    }

3.总结

实际上ThreadLocal的值是放入了当前线程的一个ThreadLocalMap实例中,所以只能在本线程中访问,其他线程无法访问。

ThreadLocal的实例以及其值仍然存放在JVM的堆。

4.问题

4.1 ThreadLocal会导致内存泄露么

如果应用使用了线程池,那么之前的线程实例处理完之后,会再次被复用,所以ThreadLocal变量会一直存在。

  • 不会发生内存泄露,ThreadLocalMap的内部实现是弱引用的,可以被JVM回收。
static class ThreadLocalMap {

/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object).  Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table.  Such entries are referred to
* as "stale entries" in the code that follows.
*/
    static class Entry extends WeakReference<ThreadLocal<?>> {
        /** The value associated with this ThreadLocal. */
        Object value;

        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }
}

4.2 使用场景

  • 实现单个线程单例以及单个线程上下文信息存储,比如交易id等
  • 实现线程安全,非线程安全的对象使用ThreadLocal之后就会变得线程安全,因为每个线程都会有一个对应的实例
  • 承载一些线程相关的数据,避免在方法中来回传递参数
时间: 2024-12-18 17:33:54

ThreadLocal的实现的相关文章

Java中ThreadLocal的深入理解

官方对ThreadLocal的描述: "该类提供了线程局部(thread-local)变量.这些变量不同于它们的普通对应物,因为访问某个变量(通过其get或set方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本.ThreadLocal实例通常是类中的private static字段,它们希望将状态与某一个线程(例如,用户ID或事物ID)相关联." <Thinking in Java>中的描述: 防止任务在共享资源上产生冲突的第二种方式是根除对变量的共享.线程本地

java 之ThreadLocal

通过 ThreadLocal 能数据保存在一个线程中,而且不需要 lock 同步.理论上 ThreadLocal 可 以让一个变量在每个线程都有一个副本. ThreadLocal 常用来屏蔽线程的私有变量,例如"并 发事务"或者其他的资源.而且,它还被用来维护每个线程的计数器,统计,或者 ID 生成 器. 由ThreadLocal常用的get方法定义看: public T get() { Thread t = Thread.currentThread(); ThreadLocalMap

图解ThreadLocal

ThreadLocal ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序. 当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本. 从线程的角度看,目标变量就象是线程的本地变量,这也是类名中"Local"所要表达的意思. 那么ThreadLocal是如何做到的呢?上图. 图没看懂?那我们来看一下源

Java中线程封闭之ThreadLocal

在访问共享数据时通常使用同步.若不使用同步则可以将对象封闭在一个线程中达到线程安全的目的,该方法称为线程封闭(Thread Confinement).其中实现线程封闭中规范的方法是使用ThreadLocal类.线程封闭技术一种常用的使用场景是在JDBC Connection对象. public class ConnectionHelper{private final static String URL = "";private final static ThreadLocal<C

ThreadLocal

为了防止内存泄露,一旦threadlocal完成任务,最好调用remove() 详见:ThreadLocal explained

并发编程(四):ThreadLocal从源码分析总结到内存泄漏

一.目录 1.ThreadLocal是什么?有什么用? 2.ThreadLocal源码简要总结? 3.ThreadLocal为什么会导致内存泄漏? 二.ThreadLocal是什么?有什么用? 引入话题:在并发条件下,如何正确获得共享数据?举例:假设有多个用户需要获取用户信息,一个线程对应一个用户.在mybatis中,session用于操作数据库,那么设置.获取操作分别是session.set().session.get(),如何保证每个线程都能正确操作达到想要的结果? /** * 回顾sync

从源码理解 ThreadLocal()

每一反应,使用Thread中定义一个成员变量来解决 线程局部变量问题: 为什么要使用ThreadLocal(),有什么好处: 单例的完整性: 解决了线程上下文中的变量传递问题,达到线程安全目的: ThreadLocal和synchronized的区别? ThreadLocal使用场景 待完成...

理解Java ThreadLocal

ThreadLocal是什么 早在JDK 1.2的版本中就提供Java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序. ThreadLocal很容易让人望文生义,想当然地认为是一个"本地线程".其实,ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易让人理解一些. 当使用ThreadLocal维护变量

我对ThreadLocal的理解

声明:小弟菜狗一个.对ThreadLocal的描写叙述和理解难免有所偏差 近期由于须要深入的了解android的handler消息机制而去查看了Looper的源代码.众所周知在主线程中是不须要在程序猿在代码新建一个Looper对象的,由于在主线程创建时它就被创建出来了.所以就好奇它是怎么被创建出来的然后发现它跟ThreadLocal 有关于是便查看了该类的一些资料,但还是不太理解.于是便尝试自己去看一下源代码,然后就有了对ThreadLocal一个又一次的认识.先贴出Looper的代码: pri

ThreadLocal实现原理

一.ThreadLocal介绍 这是一个线程的局部变量.也就是说,只有当前线程可以访问.既然是只有当前线程可以访问的数据,自然是线程安全的. 为每一个线程分配不同的对象,需要在应用层面保证.ThreadLocal只是起到了简单的容器作用. 二.实现原理 1. 我们需要关注的是ThreadLocal的set()方法和get()方法. set()方法 public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMa