ThreadLocal详解

ThreadLocal学习笔记

什么是ThreadLocal

ThreadLocal是线程变量,ThreadLocal中放的变量是属于当前线程的,该变量对于其他线程而言是隔离的。ThreadLocal为变量在每个线程中创建一个副本,每个线程可以访问自己线程内的副本。

ThreadLocal的优势:

  • 进行对象跨层传递时,使用ThreadLocal可以避免多层传递,在ThreadLocal中存取数据即可;
  • 线程间的数据隔离,每个线程维护自己的变量,对其他线程不可见;

ThreadLocal示例

package com.ludk.study.threadlocal;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author ludengke
 * @title: ThreadLocalTest
 * @projectName weixin
 * @description: TODO
 * @date 2023/11/1816:09
 */
public class ThreadLocalTest {
    public static void main(String[] args) {
        testThreadLocal();
    }
    public static void testThreadLocal(){
    	//线程变量,每个线程都有自己的变量副本
        final ThreadLocal<String> local=new ThreadLocal<String>();
        //启动了5个线程,线程的名字为线程finalI。local为线程外的公共变量,正常情况线程不安全。
        //可因为他是ThreadLocal,每个线程都有自己的变量副本,因此打印结果是线程名称和线程自己的变量。
        for (int i=0;i<5;i++){
            final int finalI = i;
            new Thread(new Runnable() {
                public void run() {
                    local.set(finalI +"啊啊啊");
                    System.out.println(Thread.currentThread().getName()+":"+local.get());
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"线程"+finalI+":").start();
        }
    }
}


线程0::0啊啊啊
线程3::3啊啊啊
线程2::2啊啊啊
线程1::1啊啊啊
线程4::4啊啊啊

Process finished with exit code 0

ThreadLocal的原码分析

ThreadLocal的设计关注三个点

  • ThreadLocal
  • ThreadLocalMap
  • Thread

先上结论:

  • Thread
    每个线程都有自己的ThreadLocalMap
  • ThreadLocalMap
    key ThreadLocal
    value 值
    比如有的地方定义了“sessionThreadLocal”,有的地方定义了“dataThreadLocal”,那ThreadLocalMap中就存储了这两个值,而且这两个值只属于当前线程,因为一个线程有自己对于的ThreadLocalMap

java.lang.ThreadLocal set

public void set(T value) {
		//获取当前线程
        Thread t = Thread.currentThread();
        //获取ThreadLoclMap
        ThreadLocalMap map = getMap(t);
        if (map != null)//如果获取到ThreadLocalMap,则放入数据,key为ThreadLocal,value为值
            map.set(this, value);
        else
        	//否则创建ThreadLocalMap
            createMap(t, value);
    }

从creatMap方法及下面图片的代码可以看出,每个线程会有自己的ThreadLocalMap

void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

在这里插入图片描述
通过ThreadLocalMap的构造方法可以看出,ThreadLocalMap的key是ThreadLocl,value是想存储的值

ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
   table = new Entry[INITIAL_CAPACITY];
   int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
   table[i] = new Entry(firstKey, firstValue);
   size = 1;
   setThreshold(INITIAL_CAPACITY);
}

ThreadLocalMap是ThreadLocal的静态内部类,是真正存储线程变量的地方
ThreadLocal的代码结构
其他方法如remove可以自己分析。

ThreadLocal的应用场景

每个线程需要自己单独的变量,这种场景均可以考虑ThreadLocal

  • 存储用户session
  • 存储数据库连接
  • 数据跨层传递
  • 解决线程安全问题:但是他与synchronized有很大的区别。synchronized是加锁,某个安全点内,只有一个线程可以访问变量。而ThreadLocal是每个线程都有自己的变量,线程间的变量是隔离开的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值