zoukankan      html  css  js  c++  java
  • 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是需要存储的变量。)

      

  • 相关阅读:
    Oracle 安装安全补丁过程中出现的问题
    Oracle 设置日志模式
    Oracle 设置archivelog错误解决方案
    sum() over() 函数的使用
    C盘清理,移动node 依赖和缓存文件
    ol设置最佳可视范围和限制缩放
    flex弹性布局模式下文字超出显示省略号
    查看svn本地账户和密码
    flutter apk启动闪退问题
    More than one file was found with OS independent path 'lib/armeabi-v7a/libflutter.so'
  • 原文地址:https://www.cnblogs.com/liuboyuan/p/10470501.html
Copyright © 2011-2022 走看看