zoukankan      html  css  js  c++  java
  • ThreadLocal学习

    源码关于类的注释初识

    源码在类的定义之前有一段注释,大体是这个意思:
    ThreadLocal类提供 thread-local variabels(线程局部变量)
    这些变量与普通变量不同,每个线程都可以通过其 get 或 set方法来访问自己的独立初始化的变量副本
    ThreadLocal的实例通常在类中是private static的一个域,这个域维持与线程相关联的某种状态(例如用户ID或事务ID)

    注释中给出了这样一个例子:

    import java.util.concurrent.atomic.AtomicInteger;
    
    public class ThreadId {
         // Atomic integer containing the next thread ID to be assigned
         private static final AtomicInteger nextId = new AtomicInteger(0);
    
         // Thread local variable containing each thread's ID
         private static final ThreadLocal<Integer> threadId =
             new ThreadLocal<Integer>() {
                 @Override protected Integer initialValue() {
                     return nextId.getAndIncrement();
             }
         };
    
         // Returns the current thread's unique ID, assigning it if necessary
         public static int get() {
             return threadId.get();
         }
     }

    ThreadId这个类对于每个线程都生成一个唯一本地标识(线程id值),这个id在第一次被调用后分配,

    并在随后的调用中保持不变

    关键代码

    public class ThreadLocal<T> {
        /**
         * 内部类ThreadLocalMap中使用,相当于HashMap中的hashCode设计
    * ThradLocalMap类设计了一个静态内部类Entry,其构造方法为(ThreadLocal<?> k,Object v)
    * 搜索Entry时,根据k.threadLocalHashCode值做下标寻址计算
    */ private final int threadLocalHashCode = nextHashCode(); /** * The next hash code to be given out. Updated atomically. Starts at zero. */ private static AtomicInteger nextHashCode = new AtomicInteger(); /** * hash增长值,设计为7
    *
    */ private static final int HASH_INCREMENT = 0x61c88647; /** * 获取下一个hash值 */ private static int nextHashCode() { return nextHashCode.getAndAdd(HASH_INCREMENT); } /**
    * 设置ThreadLocal初始值,第一次调用get()方法获取初始值的时候将调用此方法
    * 正常情况下,该方法最多只会被一个线程调用一次,但是如果后续调用了remove()方法接着调用get()时,
    * 该方法也会被调用 * 默认返回是null,如果想设置为非null值,在创建ThreadLocal时使用匿名内部类覆盖此方法
    */ protected T initialValue() { return null; } /** * lambda方式初始化,比使用匿名内部类覆盖initialValue()更易理解
    * ThreadLocal<String> local = ThreadLocal.withInitial(()->"hello")
    */ public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) { return new SuppliedThreadLocal<>(supplier); } /** * 构造方法 * @see #withInitial(java.util.function.Supplier) */ public ThreadLocal() { } /*** 核心方法,获取当前线程变量的值 * @return the current thread's value of this thread-local */ 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(); }/** * 核心方法,设置本地线程变量的值,支持泛型*/ public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); } /** * 清除变量值*/ public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) m.remove(this); } /** * 核心逻辑之一,查看Thread.java源码可以看到
    * Thread类持有一个ThreadLocal.ThreadLocalMap类型的变量threadLocals
    */ ThreadLocalMap getMap(Thread t) { return t.threadLocals; } /** * Create the map associated with a ThreadLocal. Overridden in * InheritableThreadLocal. * * @param t the current thread * @param firstValue value for the initial entry of the map */ void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }/**
    * ThreadLocal设计的一个关键部分,是它的一个静态内部类 * ThreadLocalMap的方法,除了构造方法全部是private的,因此没有任何操作会溢出ThreadLocal
    * 这是一个HashMap结构
    * 查看set方法:set(ThreadLocal<?> key,Object value),可以知道这个map以ThreadLocal对象作为key
    * 但是搜索下标,使用的是key.threadLocalHashCode做计算
    */ static class ThreadLocalMap {
    //Entry是ThreadLocalMap的一个静态内部类
    private Entry[] table; ………… } }

     使用场景

    同一个线程内 不同逻辑间需要共享数据(但又无法通过传值来共享数据),或者在同一个线程内为避免重复创建对象 而希望数据重用等情况

    注意

    对一同一个线程的不同ThreadLocal来讲,这些ThreadLocal共享一个table数组,每个ThreadLocal实例在数组中的索引不同

     
  • 相关阅读:
    php配置GD库
    Linux 安装 Apache2+php5+gd+freetype2
    gd库
    数组和链表的区别
    python 整数中1出现的次数
    python栈--字符串反转,括号匹配
    Linux基础知识
    操作系统
    后台面试问题
    python 面向对象
  • 原文地址:https://www.cnblogs.com/yb38156/p/13977014.html
Copyright © 2011-2022 走看看