Gli*_*ide 6 java concurrency spring multithreading thread-local
在下面的单例作用域服务类中,类中的所有方法都需要一些在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();
}
}
Run Code Online (Sandbox Code Playgroud)
1)示例代码是正常的,除了doB和doC中的名称冲突,其中您使用与引用ThreadLocal的静态变量相同的名称,就像保存从ThreadLocal中提取的内容的本地变量一样.
2)您存储在ThreadLocal中的对象保持附加到该线程,直到被明确删除.例如,如果您的服务在servlet容器中执行,则当请求完成时,其线程将返回池中.如果你还没有清理线程的ThreadLocal变量内容,那么该数据将随之附带,以配合线程为下一个分配的任何请求.每个线程都是GC根,附加到线程的threadlocal变量在线程死亡之前不会被垃圾收集.根据API文档:
只要线程处于活动状态且ThreadLocal实例可访问,每个线程都会保存对其线程局部变量副本的隐式引用; 在一个线程消失之后,它的所有线程局部实例副本都要进行垃圾收集(除非存在对这些副本的其他引用).
如果您的上下文信息仅限于一个服务的范围,那么最好通过参数而不是使用ThreadLocal传递信息.ThreadLocal适用于需要跨不同服务或不同层提供信息的情况,如果只有一个服务使用它,您似乎只会过度复杂化代码.现在,如果您在不同的不同对象上有AOP建议使用的数据,那么将这些数据放在threadlocal中可能是一种有效的用法.
要执行清理通常,您将确定线程使用当前处理完成的点,例如在servlet过滤器中,其中threadlocal变量可以在线程返回到线程池之前被删除.您不会使用try-finally块,因为您插入threadlocal对象的位置远离您清理它的位置.
| 归档时间: |
|
| 查看次数: |
4876 次 |
| 最近记录: |