深入理解ThreadLocal

Struts2的笔记中,在学习关于调用ServletAPI的过程中,我们接触到关于如何获取ActionContext对象,它是通过ThreadLocal设定一个为线程所独享的对象。关于ThreadLocal,我有所疑惑,所以单独列出来探索一下。

ThreadLocal的介绍


ThreadLocal在java.lang包下,译为线程局部变量,它并不是为了解决多线程共享变量而存在的,而是为每个线程创建一个独立的变量副本

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its {@code get} or {@code set} method) has its own, independently initialized copy of the variable. {@code ThreadLocal} instances are typically private static fields in classes that wish to associate state with a thread (e.g.,a user ID or Transaction ID)

大致意思是:该类提供线程局部变量,这些变量不同于通常的副本,它们会在每个线程独立初始化一个属于自己的拷贝,这就保证了即使在多线程的环境下(通过get和set方法),每个线程里的变量依然独立于其他变量。线程局部变量通常是关联线程的静态私有变量,用以关联线程以及线程的上下文。其生命周期和线程生命周期相关。
ThreadLocal显著地降低了一个线程内,多个函数、或者组件访问某个公共变量的复杂度。
ThreadLocal常常应用于按线程多实例的场景,典型应用就是Struts2中的ActionContext,以下是ActionContext源码中的静态属性。

static ThreadLocal actionContext = new ThreadLocal();

ThreadLocal的操作


ThreadLocal常用的4个方法,分别是:

initialValue()

initialValue():该方法返回局部变量的初始值,这个方法是protected方法,这意味着它能够被子类重写,事实上,它就是用来被子类重写的。这是一个延迟加载方法,只有在线程第一次调用get或者set方法时才执行,并且只执行一次,该方法的缺省返回值为null。

protected T initialValue() {
        return null;
    }

get()

该方法返回当前线程中的线程局部变量

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();
    }

如果当前线程中没有局部变量值,那么就会返回初始值。

set()

用以设定当前线程的局部变量。

public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

remove()

public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }

用以删除当前线程中的局部变量。

//TODO

你可能感兴趣的:(javaSE)