ThreadLocal源码解读内存泄漏分析

本文深入解析了JDK1.2引入的ThreadLocal工具类,阐述其在多线程程序中的作用,如对象跨层传递、线程间数据隔离、事务操作等,并通过示例代码展示如何使用。同时,分析了ThreadLocal的get、set、remove方法源码,提醒开发者注意内存泄漏问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

早在JDK1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。但是ThreadLocal并不是一个线程,他是一个线程变量。意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的。伴随整个线程生命周期存在,可以作为线程执行,对象跨层,父子线程通信,线程追踪的标记。

ThreadLocal作用

1、在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。

2、线程间数据隔离

3、进行事务操作,用于存储线程事务信息。

4、数据库连接,Session会话管理。

ThreadLocal怎么用

public class ThreadLocalTest {

    static ThreadLocal<String> local = new ThreadLocal<>();

    static void print(String str) {
        //打印当前线程中本地内存中本地变量的值
        System.out.println(str + " :" + local.get());
        //清除本地内存中的本地变量
        local.remove();
    }

    public static void main(String[] args) {
        Thread t1  = new Thread(new Runnable() {
            @Override
            public void run() {
                //设置线程1中本地变量的值
            	local.set("local1");
                //调用打印方法
                print("thread1");
                //打印本地变量
                System.out.println("after remove : " + local.get());
            }
        });

        Thread t2  = new Thread(new Runnable() {
            @Override
            public void run() {
                //设置线程1中本地变量的值
            	local.set("local2");
                //调用打印方法
                print("thread2");
                //打印本地变量
                System.out.println("after remove : " + local.get());
            }
        });

        t1.start();
        t2.start();
    }
}

ThreadLocal源码分析
重点是get,set,remove方法
get方法源码

public Object get()
    {
        Thread thread = Thread.currentThread();
        ThreadLocalMap threadlocalmap = getMap(thread);
        if(threadlocalmap != null)
        {
            ThreadLocalMap.Entry entry = threadlocalmap.getEntry(this);
            if(entry != null)
                return entry.value;
        }
        return setInitialValue();
    }

set方法源码

private void set(ThreadLocal threadlocal, Object obj)
        {
            Entry aentry[] = table;
            int i = aentry.length;
            int j = threadlocal.threadLocalHashCode & i - 1;
            for(Entry entry = aentry[j]; entry != null; entry = aentry[j = nextIndex(j, i)])
            {
                ThreadLocal threadlocal1 = (ThreadLocal)entry.get();
                if(threadlocal1 == threadlocal)
                {
                    entry.value = obj;
                    return;
                }
                if(threadlocal1 == null)
                {
                    replaceStaleEntry(threadlocal, obj, j);
                    return;
                }
            }

            aentry[j] = new Entry(threadlocal, obj);
            int k = ++size;
            if(!cleanSomeSlots(j, k) && k >= threshold)
                rehash();
        }

remove方法源码

 private void remove(ThreadLocal threadlocal)
        {
            Entry aentry[] = table;
            int i = aentry.length;
            int j = threadlocal.threadLocalHashCode & i - 1;
            for(Entry entry = aentry[j]; entry != null; entry = aentry[j = nextIndex(j, i)])
                if(entry.get() == threadlocal)
                {
                    entry.clear();
                    expungeStaleEntry(j);
                    return;
                }

        }

ThreadLocal内存泄漏问题
使用set方法移除key,但是value依然在并不会被垃圾回收器回收,value会一直持续到线程结束才会被回收,这就存在内存泄漏的可能性。可以使用remove移除value来避免内存泄漏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值