zoukankan      html  css  js  c++  java
  • ThreadLocal

    介绍

    ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

    ThreadLocal像是一个map,map的键就是每一个线程,值就是变量副本

    使用

    public class ThreadLocalDemo {
        private ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 0);
    
        public Integer getNext() {
            Integer integer = threadLocal.get();
            threadLocal.set(++integer);
            return integer;
        }
    
        public static void main(String[] args) {
            ThreadLocalDemo threadLocalDemo = new ThreadLocalDemo();
            for (int i = 0; i < 3; i++) {
                new Thread(() -> {
                    while (true) {
                        System.out.println(Thread.currentThread().getName() + threadLocalDemo.getNext());
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }
    }
    

    上面的代码中,每一个线程的值都是从0开始递增,各个线程之间互不影响。

    原理解析

    首先查看get()方法的源代码:

    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")
                // 这里可以看到最终的值是从这里拿到的,也就是说值会存在ThreadLocal下面的ThreadLocalMap里面的Entry里面的value里面	
                T result = (T)e.value;    
                return result;
            }
        }
        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;
    }
    
    void createMap(Thread t, T firstValue) {
        // 这个创建ThreadLocalMap的方法比较有趣的是它将创建好后的map赋值给了当前线程的一个属性
     	// 而在Thread类中确实有这样一个属性,如下。因此ThreadLocalMap是属于每一个线程的
        t.threadLocals = new ThreadLocalMap(this, firstValue);   
    }
    
    ThreadLocal.ThreadLocalMap threadLocals = null;
    
  • 相关阅读:
    智联招聘
    我的Linux以及软件配置(长期更新)
    关于Git的笔记
    PHP和HTML表单
    web学习笔记——CSS整理(一)
    新开通博客园
    Thinphp模板替换
    __APP__
    大步前行
    centos 7 添加环境变量
  • 原文地址:https://www.cnblogs.com/Myarticles/p/12046042.html
Copyright © 2011-2022 走看看