4月更文d20n20-利用切面统一处理threadLocal释放

296 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情

利用切面统一处理threadLocal释放

前文

本文内容主要在现有项目中,有采用每个请求中将用户的信息存储在请求线程的threadLocal中。而众所周知的一个问题是,threadLocal在使用过程中有可能存在内存的泄露问题。因此采用切面编程的方式进行一下统一的处理。

threadLocal为什么会内存泄露

在java的引用中一直存在四种常见的引用,强软弱虚四种引用。而导致threadLocal出现潜在内存泄露隐患的则是弱引用。这部分内容本文不会再重复进行赘述。大致概括来说,由于在threadLocal使用结束时,存在的强引用已经释放,而只残余threadLocalMap中的弱引用。而这种情况下该对象会在发生垃圾回收时被回收处理,也就导致了其中设置的对象数据会处于一个无法回收的状态,导致内存泄露。因此,在常规的线程结束后,我们需要手动对于threadLocal中的内容进行移除处理防止内存泄露。

使用切面统一处理

回到前文,本问题的应用场景主要是在于每个请求中。众所周知,当服务端接收到每一次的请求时,都会存在一个单独的请求线程。也就是基于这个特性,项目中在每个请求被获取到时,会首先将相关的用户信息数据,存储在当前现成的threadLocal之中。这样当后续需要进行操作时,直接从threadLocal中进行数据获取即可。而由于之前未进行保护性的防止内存泄露,因此存在该隐患。采用的解决思路主要是通过切面编程,通过拦截所有的controller,在请求处理结束时,增加一层解决内存泄露的代码。以此方式将对象中的内容释放,也就解决了可能存在的内存泄漏隐患 。

处理方案

@Aspect
public class ThreadLocalAspect{
    public ThreadLocalAspect() {
    }
    @After("execution(* xx.business.rest.*(..))")
    public void supports(ProceedingJoinPoint proceedingJoinPoint) {
//        防止threadLocal内存泄露,在请求结束后移除threadLocal中的数据
         if(BaseContext.context != null){
             BaseContext.context.remove();
         }
    }
}

后记

  • 千古兴亡多少事?悠悠。不尽长江滚滚流。