加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 关于在Spring单例作用域服务中使用ThreadLocal的问题

发布时间:2020-12-14 06:01:02 所属栏目:Java 来源:网络整理
导读:在下面的单例作用域服务类中,类中的所有方法都需要一些在调用Service.doA()时已知的用户上下文.我没有考虑在方法中传递信息,而是考虑在TheadLocal中存储这些值.关于这种方法,我有两个问题: 1)下面的实现是否正确使用ThreadLocal?也就是说,它是线程安全的,
在下面的单例作用域服务类中,类中的所有方法都需要一些在调用Service.doA()时已知的用户上下文.我没有考虑在方法中传递信息,而是考虑在TheadLocal中存储这些值.关于这种方法,我有两个问题:

1)下面的实现是否正确使用ThreadLocal?也就是说,它是线程安全的,并且正确的值将被读/写到ThreadLocal中?

2)是否需要显式清除ThreadLocal userInfo以防止任何内存泄漏?它会被垃圾收集吗?

@Service
public class Service {
    private static final ThreadLocal<UserInfo> userInfo = new ThreadLocal<>(); 

    public void doA() {
        // finds user info
        userInfo.set(new UserInfo(userId,name));
        doB();
        doC();
    }

    private void doB() {
        // needs user info
        UserInfo userInfo = userInfo.get();
    }

    private void doC() {
        // needs user info
        UserInfo userInfo = userInfo.get();
    }
}

解决方法

1)示例代码是正常的,除了doB和doC中的名称冲突,其中您使用与引用ThreadLocal的静态变量相同的名称,就像保存从ThreadLocal中提取的内容的本地变量一样.

2)您存储在ThreadLocal中的对象保持附加到该线程,直到被明确删除.例如,如果您的服务在servlet容器中执行,则当请求完成时,其线程将返回池中.如果你还没有清理线程的ThreadLocal变量内容,那么该数据将随之附带,以配合线程为下一个分配的任何请求.每个线程都是GC根,附加到线程的threadlocal变量在线程死亡之前不会被垃圾收集.根据the API doc:

Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away,all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).

如果您的上下文信息仅限于一个服务的范围,那么最好通过参数而不是使用ThreadLocal传递信息. ThreadLocal适用于需要跨不同服务或不同层提供信息的情况,如果只有一个服务使用它,您似乎只会过度复杂化代码.现在,如果您在不同的不同对象上有AOP建议使用的数据,那么将这些数据放在threadlocal中可能是一种有效的用法.

要执行清理通常,您将确定线程使用当前处理完成的点,例如在servlet过滤器中,其中threadlocal变量可以在线程返回到线程池之前被删除.您不会使用try-finally块,因为您插入threadlocal对象的位置远离您清理它的位置.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读