ThreadLocal 使用总结

ThreadLocal是JavaJava标准库提供了一个特殊的上下文神器,目的是为了在单线程执行的时候需经常传递一些相同的参数,比如传递一个状态。
比如传递一个User对象
public void process(User user) {
    checkPermission(user);
    doWork(user);
    saveStatus(user);
    sendResponse(user);
}

 为了解决这一繁杂的参数或者对象传递,则需要使用到 ThreadLocal来存储。

它的典型使用方式如下:


static ThreadLocal<User> threadLocalUser = new ThreadLocal<>();
public void processUser(user) {
    try {
        threadLocalUser.set(user);
        step1();
        step2();
    } finally {
        threadLocalUser.remove();
    }
}

 常用的手段为:

static ThreadLocal<User> threadLocalUser = new ThreadLocal<>();

注意到普通的方法调用一定是同一个线程执行的,所以,step1()step2()以及log()方法内,threadLocalUser.get()获取的User对象是同一个实例。

实际上,可以把ThreadLocal看成一个全局Map<Thread, Object>:每个线程获取ThreadLocal变量时,总是使用Thread自身作为key:

Object threadLocalValue = threadLocalMap.get(Thread.currentThread());

是因为当前线程执行完相关代码后,很可能会被重新放入线程池中,如果ThreadLocal没有被清除,该线程执行其他代码时,会把上一次的状态带进去。

 

为了保证能释放ThreadLocal关联的实例,我们可以通过AutoCloseable接口配合try (resource) {...}结构,让编译器自动为我们关闭。例如,一个保存了当前用户名的ThreadLocal可以封装为一个UserContext对象

public class UserContext implements AutoCloseable {

    static final ThreadLocal<String> ctx = new ThreadLocal<>();

    public UserContext(String user) {
        ctx.set(user);
    }

    public static String currentUser() {
        return ctx.get();
    }

    @Override
    public void close() {
        ctx.remove();
    }
}

 

注意 threadlocal它有自己的不足之处,他只能在同一个线程之间访问。不能在父子线程之间使用,为了解决这一现象,可以查看他的实现类 : 也可以查看这个博主   https://www.cnblogs.com/hama1993/p/10409740.html

 

posted @ 2020-06-04 16:55  IT路上的小白  阅读(499)  评论(0编辑  收藏  举报