说明:ThreadLocal 称为本地线程变量;在一个线程中只有一个ThreadLocal ;
通过ThreadLocal可以实现在一个线程内实现数据的共享 ;
1、ThreadLocal是如何实现线程安全的(仅在一个线程中共享数据)
因为ThreadLocal内部维护了以Map.Map中的key保存的是当前ThreadLocal所在的线程变量.map中的value值,保存的是ThreadLocal.set()所保存的值.
2、使用ThreadLocal存入多个数据如何实现.
当调用ThreadLocal.set(Value)时,value值采用Map的形式进行调用
3、采用ThreadLocal有什么问题??
内存泄漏问题????? Tomcat服务器中自己不会删除Threadlocal,所以运行一段时间后,内存占用比较严重.所以使用时需要注意删除.
所以操作完成后记得调用remove()
4、项目中ThreadLocal的使用:
在拦截器的preHandle()方法中为各个线程设置对应的值:UserThreadLocal.set(user);
在请求完成后,在afterCompletion()方法中将ThreadLocal移除 ;
public class UserInterceptor implements HandlerInterceptor{
@Autowired
private JedisCluster jedisCluster;
private static ObjectMapper objectMapper = new ObjectMapper();
//表示处理器执行之前
/**
* 1.检测Cookie中是否有值 ticket
* 2.检测redis中是否含有ticket
* 3.如果用户已经存在则将用户信息进行包装,方便购物车获取用户
* 4.如果redis和cookie中没有ticket则转向用户登陆页面
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//通过拦截器实现用户信息的拦截
String ticket = CookieUtils.getCookieValue(request, "JT_TICKET");
if(!StringUtils.isEmpty(ticket)){
String userJSON = jedisCluster.get(ticket);
if(!StringUtils.isEmpty(userJSON)){
User user =
objectMapper.readValue(userJSON,User.class);
//如何将user数据封装 方便购物车获取???
//request.setAttribute("user", user);
//session不可以
UserThreadLocal.set(user);
return true; //拦截器放行
}
}
//如果程序执行到这里表示用户没有登陆则跳转到登陆页面
response.sendRedirect("/user/login.html");
return false;
}
//处理器执行之后
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
}
//请求完成之后
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
//程序执行 表示请求完成 线程的工作完成 将ThreadLocal移除
UserThreadLocal.remove();
}
}