zoukankan      html  css  js  c++  java
  • 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.不为空,直接移除。

  • 相关阅读:
    Ajax的个人总结
    JSON和计算机网络的个人总结
    Bootstrap内辅助类,响应式工具,组件的个人总结
    Bootstrap内栅格布局,表格,按钮,图片的个人总结
    [BUG] Linux font family error #153
    WPF在WindowStyle=None时去掉顶部白条
    WPF 之 左键弹出操作菜单,并禁用右键菜单
    WPF 气泡提示框的简单实现
    WPF TextBox 如何简单粗暴的实现水印效果?
    c#笔记--WPF文本框和密码框添加水印效果(背景文字提示)
  • 原文地址:https://www.cnblogs.com/quyangyang/p/11189751.html
Copyright © 2011-2022 走看看