暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

JAVA中ThreadLocal的用法

原创 魏尚乾 2024-05-08
167

早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路,下面就根据作者的理解来讨论一下它的用法。

首先,从名字上看,ThreadLocal肯定是跟Thread相关的,确实,咱们去看Thread源码就可以看这样一个成员变量:

ThreadLocal.ThreadLocalMap threadLocals = null;

其中ThreadLocalMap中这样定义了一个entry:

    static class Entry extends WeakReference> {
/** The value associated with this ThreadLocal. */
Object value;

Entry(ThreadLocal k, Object v) {
super(k);
value = v;
}
}

通过源码咱们可以不必深究,把ThreadLocalMap看成是ThreadLocal对象为key,Object为值的map就行。

然后重点来了, ThreadLocal里面最重要的2个方法:

/**

 * Returns the value in the current thread's copy of this
* thread-local variable. If the variable has no value for the
* current thread, it is first initialized to the value returned
* by an invocation of the {@link #initialValue} method.
*
* @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();
}
/**
     * Sets the current thread's copy of this thread-local variable
     * to the specified value.  Most subclasses will have no need to
     * override this method, relying solely on the {@link #initialValue}
     * method to set the values of thread-locals.
     *
     * @param value the value to be stored in the current thread's copy of
     *        this thread-local.
     */
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            map.set(this, value);
        } else {
            createMap(t, value);
        }
    }

可以看出,ThreadLocal的set方法是把一个对象直接绑定在当前线程的 ThreadLocalMap中,然后通过get方法拿取 ,这样只要在当前线程没有执行完的情况下,保存在ThreadLocalMap中的对象可以随时通过ThreadLocal作为key拿取。

而不同的线程中的ThreadLocalMap是互不干扰的。说简单点就是将一个对象绑定在当前线程上,只要当前线程有效,这个对象就会一直有效。根据其特性,咱们就可以利用它实现类似session的功能。

首先在拦截中验证链接的合法性,拿到用户的信息,通过ThreadLocal保存,那么在后续程序中就可以直接通过ThreadLocal拿到用户信息了,上代码:


public class UserSession {
private static final ThreadLocal<UserInfo> session= new ThreadLocal<>();

public static void clear () {
session.remove();
}
public static void addUserInfo(UserInfo userInfo) {
UserSession.clear();
session.set(userInfo);
}
public static UserInfo getUserInfo() {
return session.get();
}
}

这样在拦截器中UserSession.addUserInfo(userInfo)保存用户信息,在Controller中任何地方就可以通过UserSession.getUserInfo()获得用户信息了

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论