美文网首页
ThreadLocal 详解

ThreadLocal 详解

作者: 01_小小鱼_01 | 来源:发表于2018-05-01 23:43 被阅读2次

ThreadLocal,我们一般称之为线程的局部变量,或者是线程的本地变量。很多人认为他与多线程的同步机制相关,其实是错误的。ThreadLocal虽然提供了一种解决多线程环境下成员变量的问题,但是它并不是解决多线程共享变量的问题。

Thread、ThreadLocal、ThreadLocalMap的关系

来看看其有哪些实际的地方使用到过。

public class SeqCount {
    private static ThreadLocal<Integer> seqCount = new ThreadLocal<Integer>(){
        // 实现initialValue()
        public Integer initialValue() {
            return 0;
        }
    };

    public int nextSeq(){
        seqCount.set(seqCount.get() + 1);
        return seqCount.get();
    }

    public static void main(String[] args){
        SeqCount seqCount = new SeqCount();

        SeqThread thread1 = new SeqThread(seqCount);
        SeqThread thread2 = new SeqThread(seqCount);
        SeqThread thread3 = new SeqThread(seqCount);
        SeqThread thread4 = new SeqThread(seqCount);

        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
    }

    private static class SeqThread extends Thread{
        private SeqCount seqCount;

        SeqThread(SeqCount seqCount){
            this.seqCount = seqCount;
        }

        public void run() {
            for(int i = 0 ; i < 3 ; i++){
                System.out.println(Thread.currentThread().getName() + 
                                   " seqCount :" + seqCount.nextSeq());
            }
        }
    s}
}

运行结果如下:


运行结果
二、源码解析

ThreadLocal定义了四个方法:

  • get():返回此线程局部变量的当前线程副本中的值。
public T get( ) {
    // 获取当前线程
    Thread t = Thread.currentThread();
    // 获取当前线程的成员变量 threadLocal
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        // 从当前线程的ThreadLocalMap获取相对应的Entry
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null)
            return (T)e.value;
    }
    return setInitialValue();
}

// getMap()方法可以获取当前线程所对应的ThreadLocalMap,如下:
ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}
  • set(T value):将此线程局部变量的当前线程副本中的值设置为指定值
public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

/*
 ** 获取当前线程所对应的ThreadLocalMap,如果不为空,则调用ThreadLocalMap的set()方法,
 ** key就是当前ThreadLocal,如果不存在,则调用createMap()方法新建一个
 */
void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}
  • initialValue():返回此线程局部变量的当前线程的“初始值”。
protected T initialValue() {
    return null;
}

该方法定义为protected级别且返回为null,很明显是要子类实现它的,所以我们在使用ThreadLocal的时候一般都应该覆盖该方法。该方法不能显示调用,只有在第一次调用get()或者set()方法时才会被执行,并且仅执行1次。

  • remove():移除此线程局部变量当前线程的值。
public void remove() {
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null)
        m.remove(this);
}

该方法的目的是减少内存的占用。当然,我们不需要显示调用该方法,因为一个线程结束后,它所对应的局部变量就会被垃圾回收。

ThreadLocal的一个内部类:ThreadLocalMap,他承担了ThreadLocal的存储工作。看看ThreadLocalMap定义:

static class Entry extends WeakReference<ThreadLocal<?>> {
        /** The value associated with this ThreadLocal. */
        Object value;
        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
}

相关文章

  • ThreadLocal和InheritableThreadLoc

    ThreadLocal详解 - 简书 InheritableThreadLocal详解 - 简书 ThreadLo...

  • InheritableThreadLocal详解

    1、简介 在上一篇 ThreadLocal详解 中,我们详细介绍了ThreadLocal原理及设计,从源码层面上分...

  • ThreadLocal 详解

    ThreadLocal 详解 1. 前言 ThreadLocal是java线程中的局部变量,变量作用域仅在当前线程...

  • ThreadLocal详解

    1、简介 ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Th...

  • ThreadLocal详解

    ThreadLocal之前我认为就是内部维护了一个ThreadLocalMap其中key为当前线程(Thread....

  • ThreadLocal详解

    介绍 顾名思义这个类提供线程局部变量每个线程(通过其get或set方法)都有自己独立初始化的变量副本 Thread...

  • ThreadLocal 详解

    ThreadLocal,我们一般称之为线程的局部变量,或者是线程的本地变量。很多人认为他与多线程的同步机制相关,其...

  • ThreadLocal详解

    ThreadLocal在java.lang包中,其主要作用是提供一个和线程绑定的变量环境,即通过ThreadLoc...

  • ThreadLocal详解

    ThreadLocal说明 ThreadLocal是一个线程内部的数据存储类,使用它来保存数据,只有当前的线程才可...

  • ThreadLocal详解

    ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量。 这个玩意有什么用处,或者说为什么要有这么一个...

网友评论

      本文标题:ThreadLocal 详解

      本文链接:https://www.haomeiwen.com/subject/pgxqrftx.html