ThreadLocal

该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。

线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。Java 提供 ThreadLocal 类来支持线程局部变量,是一种实现线程安全的方式

 

ThreadLocal提供了一种访问某个变量的特殊方式:访问到的变量属于当前线程,即保证每个线程的变量不一样,而同一个线程在任何地方拿到的变量都是一致的,这就是所谓的线程隔离。

 

ThreadLocal被称为线程局部变量,就相当于把数据存储于线程本地,取也是在本地内存读取,就不会像synchronized需要频繁的修改主内存的数据,再把数据复制到工作内存,也大大提高访问效率。

 

作用:

threadlocal用于存取线程独享数据,提高访问效率

 

举例

 1 public class Demo {
 2 
 3     private ThreadLocal<Integer> count = new ThreadLocal<Integer>(){
 4         @Override
 5         protected Integer initialValue() {
 6             return new Integer(0);
 7         }
 8     };
 9 
10     public int getNext(){
11         Integer value = count.get();
12         value++;
13         count.set(value);
14         return value;
15     }
16 
17     public static void main(String[] args) {
18         Demo d =new Demo();
19 
20         new Thread(new Runnable() {
21             @Override
22             public void run() {
23                 while (true){
24                     System.out.println(Thread.currentThread().getName()+" "+d.getNext());
25                     try {
26                         Thread.sleep(1000);
27                     } catch (InterruptedException e) {
28                         e.printStackTrace();
29                     }
30                 }
31             }
32         }).start();
33 
34         new Thread(new Runnable() {
35             @Override
36             public void run() {
37                 while (true){
38                     System.out.println(Thread.currentThread().getName()+" "+d.getNext());
39                     try {
40                         Thread.sleep(1000);
41                     } catch (InterruptedException e) {
42                         e.printStackTrace();
43                     }
44                 }
45             }
46         }).start();
47 
48         new Thread(new Runnable() {
49             @Override
50             public void run() {
51                 while (true){
52                     System.out.println(Thread.currentThread().getName()+" "+d.getNext());
53                     try {
54                         Thread.sleep(1000);
55                     } catch (InterruptedException e) {
56                         e.printStackTrace();
57                     }
58                 }
59             }
60         }).start();
61 
62     }
63 
64 }

Console()

Thread-0 1
Thread-1 1
Thread-2 1
Thread-0 2
Thread-1 2
Thread-2 2

。。。。。。

 

源码分析:

 

get(),set(),remove()

    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

Thread.currentThread()拿到当前线程绑定

值最终存储到了 ThreadLocalMap 下的 Entry 的 value 里

如果 ThreadLocalMap 为空,return  setInitialValue()

    private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }

调用 initialValue()  方法 ,默认返回空,

拿到当前线程,ThreadLocalMap ,getMap()

如果map不等于空,就把当前值设置进去,map为空,就创建map

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

  

 ThreadLocalMap map = getMap(t);

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

当前线程的ThreadLocals,ThreadLocalMap 是 ThreadLocal 里引用的实例

获取时给线程绑定上threadLocals

ThreadLocal.ThreadLocalMap threadLocals = null;


ThreadLocalMap是ThreadLocal的静态内部类

静态类中引入静态类 Entry
    static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

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

ThreadLocal<?> 为key Object 作为值

 

set()

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

remove

     public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }  

获取到ThreadLocalMap.不为空,直接移除。

 

 

 

posted @ 2019-07-15 16:36  曲阳阳  阅读(145)  评论(0编辑  收藏  举报