ThreadLocal 简单介绍

Threadlocal:当前线程副本
具体定义:当使用ThreadLocal维护变量时,ThreadLocal为每一个使用该变量的线程提供独立的变量副本。
这样每个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。
从线程的角度看:目标变量就像是线程的本地变量,这样类名中"Local"所要表达的含义

先看看一个案例
public class ThreadLocalTest {
    //-------------ThreadLocal修饰的对象----------
    private static ThreadLocal<Integer> threadLcoalNum = new ThreadLocal<Integer>(){
        protected Integer initialValue() {
            return 0;
        }
    }; 
    public int getThreadLocalObject(){
        threadLcoalNum.set(threadLcoalNum.get()+1);
        return threadLcoalNum.get();
    }
    
    //-------------非ThreadLocal修饰的对象----------
    private Integer NothreadLcoalNum = 1;
    public Integer getNothreadLocalObject(){
        return NothreadLcoalNum++; 

    }

 

    //测试
    public static void main(String[] args) {
         ThreadLocalTest th = new ThreadLocalTest();
         TestClient testClient = new TestClient(th);
         new Thread(testClient).start();
         new Thread(testClient).start();     
    }
}


public class TestClient implements Runnable{
    private ThreadLocalTest threadLocalTest;
    public TestClient(ThreadLocalTest threadLocalTest){
        this.threadLocalTest = threadLocalTest;
    }
    @Override
    public void run() {
        for(int i=0;i<3;i++){
            //threadlcoal 变量测试
            System.out.println(Thread.currentThread().getName()+":"+threadLocalTest.getThreadLocalObject());
            //非threadlcoal 变量测试
            System.out.println(Thread.currentThread().getName()+":"+threadLocalTest.getNothreadLocalObject());
        }     
    }
}

结果集
----使用ThreadLocal
Thread-0:1
Thread-1:1
Thread-0:2
Thread-1:2
Thread-0:3
Thread-1:3
---未使用
Thread-0:1
Thread-1:2
Thread-0:3
Thread-1:4
Thread-0:5
Thread-1:6

从结果集中我们可以看到2个线程之间的变量是毫无影响的。奇怪呀!!!感觉ThreadLocal好强大的
我们来看看ThreadLocal<T>的类
void set(T value) 设置当前线程的线程局部变量的值
void T get() 该方法返回当前线程所对应的线程局部变量
protected T initialValue() 初始化 用protected 显然是为了子类准备,我在代码中有使用
public void remove() 删除当前线程的局部变量

分析主要方法:
  ThreadLocal的set/get 方法源码 
  public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

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

    }

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

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

上述的set方法中,我们看到了ThreadLocalMap是来自当前的线程,而map里面的key值是this指向是Threadlocal对象,value就是你所设置的对象。
在网上查询资料时候,发现有人说map的key是当前线程,很是迷糊...有点不解。
所以ThreadLocal实现,可以这样的理解:
1.每个线程带了一个ThreadLocalMap,在map中key值是ThreadLocal对象,value值就是你所设置的对象。
2.下次这个线程来请求这个资源时候,通过ThreadLocal的get() 获取这个线程的map。
3.在map中根据当前对象(ThreadLocal对象)作为key值,获取你之前所设置的对象。
这样大家就相互不干扰,皆大欢喜了。


   







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值