不规范使用ThreadLocal导致bug如何解决

发布时间:2023-01-09 09:32:07 作者:iii
来源:亿速云 阅读:141

这篇文章主要讲解了“不规范使用ThreadLocal导致bug如何解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“不规范使用ThreadLocal导致bug如何解决”吧!

因为线程重用导致的信息错乱的bug

ThreadLocal一般用于线程间的数据隔离,通过将数据缓存在ThreadLocal中,可以极大的提升性能。但是,如果错误的使用Threadlocal,可能会引起不可预期的bug,以及造成内存泄露。

有时我们会在一个接口中缓存某些数据到ThreadLocal中,但是我们要意识到,处理请求的这些线程是由tomcat提供的,而tomcat提供的线程都是配置在一个线程池中的。

也就是说,线程是可能被重用的,如果线程一旦被重用,而ThreadLocal的数据没有及时重置,就会导致数据被混乱使用。

以下方的接口为例,先获取当前线程中保存的数据信息,将参数中的name保存到ThreadLocal中以后,再获取一次。

@GetMapping(value = "/threadLocal")
public ResponseEntity<Object> threadLocal(String name) {
  String before = Thread.currentThread().getName() + ":" + threadLocal.get();
  //先获取值,理论上应该是null
  System.out.println("before:" + before);
  threadLocal.set(name);
  String after = Thread.currentThread().getName() + ":" + threadLocal.get();
  //设置完参数值再获取一次
  System.out.println("after:" + after);
  return ResponseEntity.ok().build();
}

为了尽快复现线程重用导致的问题,我们将servlet.tomcat.threads.max设置为1,这样每次请求使用的都是同一个线程。

不规范使用ThreadLocal导致bug如何解决

第一次请求接口,数据看起来很正常:

不规范使用ThreadLocal导致bug如何解决

但是第二次请求接口时,可以看到线程仍然是http-nio-8080-exec-1,但是before却打印出了第一次请求的参数test。

不规范使用ThreadLocal导致bug如何解决

这就是因为没有及时重置ThreadLocal导致的数据错误。

正确使用的姿势

修正的办法就是处理完接口之后要及时清理ThreadLocal。

@GetMapping(value = "/threadLocal")
public ResponseEntity<Object> threadLocal(String name) {
  try {
    String before = Thread.currentThread().getName() + ":" + threadLocal.get();
    //先获取值,理论上应该是null
    System.out.println("before:" + before);
    threadLocal.set(name);
    String after = Thread.currentThread().getName() + ":" + threadLocal.get();
    //设置完参数值再获取一次
    System.out.println("after:" + after);
  } finally {
    //清理数据
    threadLocal.remove();
  }
  return ResponseEntity.ok().build();
}

更优雅的处理方式

可能也有的朋友会说,每次都要使用try finally处理线程数据,未免也太麻烦了。其实,我们可以使用拦截器或者过滤器自动帮我们完成数据的初始化以及清理工作。

不规范使用ThreadLocal导致bug如何解决

感谢各位的阅读,以上就是“不规范使用ThreadLocal导致bug如何解决”的内容了,经过本文的学习后,相信大家对不规范使用ThreadLocal导致bug如何解决这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

推荐阅读:
  1. Java并发编程学习之ThreadLocal源码详析
  2. 怎么在java中使用ThreadLocal

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

threadlocal

上一篇:如何动态引入DynamicImport

下一篇:SpringBoot如何实现设置全局和局部时间格式化

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》