1, Scene
- The life cycle of the container t thread pool is different from that of the request, so the ThreadLocal parameter isolation of the request domain cannot be saved
- The request domain needs to reclaim ThreadLocal manually every time. The solution of custom thread pool will not be considered temporarily
- For classes with unsafe threads such as simpleDateFormat and DecimalFormat, set scope to ensure thread safety, and avoid repeatedly creating and wasting memory space
2, Solutions
- Interceptor Based ThreadLocal collector
- ThreadLocal auto clean up registration
- Tags for HTTP requests
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ThreadLocalCleaner {
private static final List<ThreadLocal<?>> CONTAINER = Lists.newArrayList();
public static void register(ThreadLocal<?>... threadLocal) {
if(ArrayUtils.isNotEmpty(threadLocal)) {
// Can be optimized
CONTAINER.addAll(Arrays.asList(threadLocal));
}
}
public static void clear() {
CONTAINER.forEach(ThreadLocal::remove);
}
}
public class ThreadLocalInterceptor extends HandlerInterceptorAdapter {
/**
* Whether it is a thread from http
*/
private static final ThreadLocal<Boolean> IS_HTTP_REQUEST = new ThreadLocal<>();
static {
ThreadLocalCleaner.register(IS_HTTP_REQUEST);
}
public static boolean isHttpReqThread() {
return Boolean.TRUE.equals(IS_HTTP_REQUEST.get());
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//thread local set
IS_HTTP_REQUEST.set(Boolean.TRUE);
return super.preHandle(request, response, handler);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//thread local remove
ThreadLocalCleaner.clear();
super.afterCompletion(request, response, handler, ex);
}
}