通过将对象改变成不可见对象,来保证线程安全。但是这样是躲避并发问题,除了不可见对象,还有一种解决办法 “线程封闭”
1.ad-hoc: 代码控制实现,最糟糕,这里忽略
2.堆栈封闭: 局部变量,无并发问题(高并发下,全局变量容易引起并发问题,所以能用局部变量就用局部变量)
3.threadlocal线程封闭: 特别好的封闭方法.
这里顺便写一下SpringBoot下拦截器filter的示例
public class HttpFilter implements Filter {
@Override
public void init(FilterConfig filterConfig)throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)throws IOException, ServletException {
//强转servletRequest为HttpServletRequest
HttpServletRequest request = (HttpServletRequest)servletRequest;
//获取session中的值
// request.getSession().getAttribute("user");
Cookie[] cookies = request.getCookies();
for(Cookie cookie: cookies){
//do something...
}
RequestHolder.add(Thread.currentThread().getId());
//保证拦截器拦截后,请求继续执行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
需要在启动类中注册拦截器
@Bean
public FilterRegistrationBean httpFilter(){
FilterRegistrationBean registrationBean =new FilterRegistrationBean();
registrationBean.setFilter(new HttpFilter());
registrationBean.addUrlPatterns("/threadLocal/*");
return registrationBean;
}
这里如果是多个拦截器可以写多个bean用setOrder(Integer orderNum)来控制,小的先执行
这里是监听器的示例
public class HttpInterceptor extends HandlerInterceptorAdapter{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {
log.info("prehandl");
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {
RequestHolder.remove();
log.info("afterCompletion");
return;
}
}
启动类需要注册
@Configuration
static class WebMvcConfigimplements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HttpInterceptor()).addPathPatterns("/**");
}
}
网友评论