• java多线程-ThreadLocal


    大纲:

    1. 用法
    2. 源码

    一、用法

    ThreadLocal是一个容器,顾名思义就是把一个变量存到线程本地。

    class Test {
        public static void main(String[] args)  {
            new Thread(new TestLocal()).start();
            new Thread(new TestLocal()).start();
            new Thread(new TestLocal()).start();
        }
    }
    
    class TestLocal implements Runnable {
        ThreadLocal<String> localName = new ThreadLocal<>();
    
        @Override
        public void run() {
            localName.set(Thread.currentThread().getName());
            System.out.println(localName.get());
        }
    }
    
    /**结果:
     * Thread-0
     * Thread-1
     * Thread-2
     */

    二、源码

    ThreadLocal是线程本地变量,因此每个Thread对象内部必然存储ThreadLocal,ThreadLocal作为key,存储在ThreadLocalMap中。

    class Thread {
        ThreadLocal.ThreadLocalMap threadLocals = null; //每个线程对象内部维护了一个ThreadLocal.ThreadLocalMap。
        ...
    }

    ThreadLocal主要方法就是set,get

    • set:
    public class ThreadLocal<T> {
    
        static class ThreadLocalMap {...} //ThreadLocalMap是ThreadLocal的静态内部类
        ...
    
        public void set(T value) {
            Thread t = Thread.currentThread(); //拿到当前线程
            ThreadLocalMap map = getMap(t); //取出线程维护的ThreadLocalMap
            if (map != null)
                map.set(this, value); //ThreadLocalMap的key为当前ThreadLocal对象,value就是我们需要存储的变量
            else
                createMap(t, value); //该线程第一次使用ThreadLocal.set时创建ThreadLocalMap对象,并赋值。
        }
    
        void createMap(Thread t, T firstValue) {
            t.threadLocals = new ThreadLocalMap(this, firstValue);
        }
    
        ThreadLocalMap getMap(Thread t) {
            return t.threadLocals;
        }

      ... }
    • get:
    public class ThreadLocal<T> {
    
        public T get() {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t); //从当前线程取出ThreadLocalMap
            if (map != null) {
                ThreadLocalMap.Entry e = map.getEntry(this); //以当前ThreadLocal对象为key取出ThreadLocalMap.Entry
                if (e != null) {
                    T result = (T)e.value;
                    return result;
                }
            }
            return setInitialValue(); //如果这个ThreadLocal对象没有赋值直接get,会给它赋值为null并返回。
        }
    
        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;
        }
    
        protected T initialValue() {
            return null;
        }

      ... }

    ThreadLocal get、set思想小结:

    1. 拿到当前线程对象。
    2. 拿到线程对象内部维护的ThreadLocalMap对象。
    3. 一个线程对象中只有一个ThreadLocalMap对象,所有ThreadLocal对象及这个ThreadLocal对象存储的值都以key-value的形式存在ThreadLocalMap中。(ThreadLocalMap的key是ThreadLocal对象,value是需要存储的变量。)

      

  • 相关阅读:
    day04
    day02
    day01
    if语句用户交互字符串
    python安装和pycharm安装教程
    day1预习
    博客园的使用
    python day 3
    从cbv到fbv:用函数写视图与用类写视图的区别(drf与restful)
    resful规范: 进行数据交换时的代码潜规则
  • 原文地址:https://www.cnblogs.com/liuboyuan/p/10470501.html
Copyright © 2020-2023  润新知