您的位置:首页 > 其它

ThreadLocal 简单介绍

2016-04-13 22:15 399 查看
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值,获取你之前所设置的对象。

这样大家就相互不干扰,皆大欢喜了。

   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: