zoukankan      html  css  js  c++  java
  • 一步一步学多线程-ThreadLocal源码解析

      上网查看了很多篇ThreadLocal的原理的博客,上来都是文字一大堆,费劲看了半天,大脑中也没有一个模型,想着要是能够有一张图明确表示出来ThreadLocal的设计该多好,所以就自己看了源码,画了一张图出来,立刻清晰不少。

    根据源码代码理清ThreadLocal结构

     1 public T get() {
     2     Thread t = Thread.currentThread();
     3     ThreadLocalMap map = getMap(t);
     4     if (map != null) {
     5         ThreadLocalMap.Entry e = map.getEntry(this);
     6         if (e != null) {
     7             @SuppressWarnings("unchecked")
     8             T result = (T)e.value;
     9             return result;
    10         }
    11     }
    12     return setInitialValue();
    13 }
    1 ThreadLocalMap getMap(Thread t) {
    2     return t.threadLocals;
    3 }
    1 ThreadLocal.ThreadLocalMap threadLocals = null;
    1 private Entry getEntry(ThreadLocal<?> key) {
    2     int i = key.threadLocalHashCode & (table.length - 1);
    3     Entry e = table[i];
    4     if (e != null && e.get() == key)
    5         return e;
    6     else
    7         return getEntryAfterMiss(key, i, e);
    8 }

      通过上面的代码可以看出来,在每个线程里面都保存了ThreadLocalMap,而ThreaLocalMap里面又存储了以ThreadLocal为键值的Entry数组。

      用一张图来表示更清楚

          

    ThreatLocal的Set步骤 

      先看ThreadLocal的set方法,我们看一下ThreatLocal具体是怎么操作的

    1 public void set(T value) {
    2     Thread t = Thread.currentThread();
    3     ThreadLocalMap map = getMap(t);
    4     if (map != null)
    5         map.set(this, value);
    6     else
    7         createMap(t, value);
    8 }
    1 void createMap(Thread t, T firstValue) {
    2     t.threadLocals = new ThreadLocalMap(this, firstValue);
    3 }

      通过上面的代码可以看出来ThreadLocal的存储

      1、  获取当前线程

      2、  获取到当前线程中的ThreadLocalMap

      3、  如果获取到的ThreadLocalMap不为null,就以当前ThreadLocal对象为键,以要插入的值为值,ThreadMapLocalMap中。

      4、  如果获取的的ThreadLocalMap为null,则创建一个ThreadLocalMap对象

    ThreadLocal的Get步骤

      

     1 public T get() {
     2     Thread t = Thread.currentThread();
     3     ThreadLocalMap map = getMap(t);
     4     if (map != null) {
     5         ThreadLocalMap.Entry e = map.getEntry(this);
     6         if (e != null) {
     7             @SuppressWarnings("unchecked")
     8             T result = (T)e.value;
     9             return result;
    10         }
    11     }
    12     return setInitialValue();
    13 }
     1 private T setInitialValue() {
     2     T value = initialValue();
     3     Thread t = Thread.currentThread();
     4     ThreadLocalMap map = getMap(t);
     5     if (map != null)
     6         map.set(this, value);
     7     else
     8         createMap(t, value);
     9     return value;
    10 }

      通过上面的代码可以看出来ThreadLocal的Get步骤为

      1、  获取当前线程

      2、  根据当前线程获取线程中的ThreadLocalMap

      3、  如果获取到的ThreadLocalMap不为null,则以当前ThreadLocal为键,获取存储在ThreadLocalMap中的值并返回

      4、  如果获取到的ThreadLocalMap为null,则创建一个以当前对象为键的对象,以ThreadLocal设置的初始值为值,存入ThreadLocalMap中,然后返回。

    ThreaLocal中的初始值设置

    1 protected T initialValue() {
    2     return null;
    3 }

      上面这个initalValue方法是在创建ThreadLocalMap时候的value值的默认初始值,代码中默认返回的是null,我们可以通过自己在代码中自己设计值。

  • 相关阅读:
    ssh密钥讲解
    Python之paramiko模块
    Python之socket编程进阶版
    linux内socket服务器无法连接windows
    Python之socket编程
    linux(centOS7,mini),python环境的搭建
    Python 之异常处理机制
    pytho常用模块2——random
    Hadoop基础(二):从Hadoop框架讨论大数据生态
    Hadoop基础(一):概论
  • 原文地址:https://www.cnblogs.com/fhhk/p/7384545.html
Copyright © 2011-2022 走看看