不规范使用ThreadLocal导致的bug,说多了都是泪

news2024/11/19 14:35:08

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

因为线程重用导致的信息错乱的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,这样每次请求使用的都是同一个线程。

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

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

这就是因为没有及时重置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处理线程数据,未免也太麻烦了。其实,我们可以使用拦截器或者过滤器自动帮我们完成数据的初始化以及清理工作。

最后

我们在写业务代码时,正确的理解线程的全生命周期以及执行原理,对我们提升代码的健壮性其实很有帮助。有时我们觉得底层原理很枯燥乏味,开发业务就是写增删改查,多线程用的也很少,但我们只是没有意识到,我们的代码一直跑在tomcat提供的线程池中,本身就是一个多线程的环境。

除了tomcat的线程池,我们自定义的线程池其实也会有这个问题,大家可以看看自己的业务代码是否踩过这个坑。

感谢您的点赞和关注。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/183579.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一起自学SLAM算法:11.2 环境感知

连载文章&#xff0c;长期更新&#xff0c;欢迎关注&#xff1a; 环境感知就是机器人利用传感器获取自身及环境状态信息的过程&#xff0c;自主导航机器人的环境感知主要包括实时定位、环境建模、语义理解等&#xff0c;下面具体讨论。 11.2.1 实时定位 定位其实就是在回答图…

BI技巧丨近两年及当年月份数据汇总

BOSS&#xff1a;白茶&#xff0c;有个需求&#xff0c;不知道你能不能做&#xff1f; 白茶&#xff1a;不能&#xff01; BOSS&#xff1a;我还没说呢&#xff0c;小伙砸&#xff01;做了加钱&#xff01; 白茶&#xff1a;BOSS您吩咐&#xff01; BOSS&#xff1a;是这样的&a…

C语言开发基于RT-Thread家庭安全环境检测系统源码,RTT设计大赛

基于RT-Thread家庭安全环境检测 简介 基于RT-Thread和中蓝讯科的AB32VG1开发板实现的家庭安全检测功能&#xff0c;主要包含如下功能&#xff1a; 1、基于RT-Thread操作系统的按键组件&#xff0c;音频播放组件等&#xff1b; 2、基于AB32VG1开发板的语音播放功能&#xff1b…

BlackByte勒索软件开始使用新的数据泄露工具ExByte

BlackByte 勒索软件在 2021 年被首次发现&#xff0c;随后不断发现其变种。BlackByte 勒索软件不仅使用双重勒索&#xff0c;还运营着勒索软件即服务&#xff08;RaaS&#xff09;。最近&#xff0c;研究人员发现 BlackByte 开始使用名为 ExByte 的数据泄露工具来窃取受害者的数…

什么品牌的蓝牙耳机音质好?四款高音质蓝牙耳机推荐

随着时代的发展&#xff0c;蓝牙耳机的使用频率越来越高&#xff0c;在日常生活中随处可见的戴蓝牙耳机的人。或是听音乐&#xff0c;或是追剧&#xff0c;或是玩游戏等等。在现如今众多的蓝牙耳机品牌当中&#xff0c;什么品牌的蓝牙耳机音质好&#xff1f;下面&#xff0c;我…

基于Yolo实现的交通路况汽车识别 附完整代码(使用Keras框架)

一、问题描述 假设你现在在做自动驾驶的汽车,你想着首先应该做一个汽车检测系统,为了搜集数据,你已经在你的汽车前引擎盖上安装了一个照相机,在你开车的时候它会每隔几秒拍摄一次前方的道路。 您已经将所有这些图像收集到一个文件夹中,并通过在您找到的每辆车周围画边界框…

BlackStone:一款功能强大的渗透测试报告工具

关于BlackStone BlackStone是一款功能强大的渗透测试报告工具&#xff0c;该项目可以帮助广大研究人员自动起草和提交渗透测试或安全研究审计报告。该工具允许我们在数据库中提交和存储渗透测试过程中发现的漏洞&#xff0c;并通过内部和外部审计来对漏洞进行分类。除此之外&a…

界面控件DevExpress WinForm的先进技术——服务器和即时反馈模式

DevExpress WinForm拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForm能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜任…

vue中如何优雅的实现数字递增特效

需求 前几天项目开发中遇到一个需求&#xff0c;需要在数字更新时&#xff0c;实现其动态递增的效果 并且&#xff0c;在数字大于10000时&#xff0c;将单位进行转换&#xff0c;如数字大于10000时&#xff0c;单位从m变为万m 我们以vue中开发为例&#xff0c;一一实现下这两个…

多目标跟踪(MOT)入门介绍

1. 相关方向 这些是我所了解的多目标跟踪&#xff08;MOT&#xff09;的一些相关方向。其中单目标跟踪&#xff08;VOT/SOT&#xff09;、目标检测&#xff08;detection&#xff09;、行人重识别&#xff08;Re-ID&#xff09;都是非常热门的方向。而偏视频的相关方向就比较冷…

java 随机数种子 java设置随机数种子教程 java随机数种子怎么设置

我们常用的随机数生成就是Math.random()&#xff1b;java.util.Random类有两种方式构建方式&#xff1a;带种子和不带种子import java.util.Random;不带种子&#xff1a;不带种子将会返回随机的数字&#xff0c;每次运行结果不一样public class RandomTest {public static void…

分享149个ASP源码,总有一款适合您

ASP源码 分享149个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 149个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/173AhCXJgM5AvPqBw-la60w?pwdqk9j 提取码&#x…

如何在UI自动化测试中加入REST API的操作

1、问题 当我们描述一个“好的自动化测试用例”时&#xff0c;经常出现标准是&#xff1a; 精确 自动化测试用例应该测试一件事&#xff0c;只有一件事。与测试用例无关的应用程序的某个部分中的错误不应导致测试用例失败。 独立 自动化测试用例不应该受测试套件中任何其他测…

SVN服务端使用教程

前言 正式进入公司项目后&#xff0c;我们需要和同事进行协同开发&#xff0c;此时代码管理工具是必不可少的&#xff0c;目前常用的两款工具是&#xff1a;SVN 和 Git。本人因为要搭建一个自动化测试的框架&#xff0c;对SVN和Git都不熟悉&#xff0c;在调研后选择了操作更为…

组合选择器

<!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>组合选择器</title> <style type"text/css"> /* 多个选择器组合在一起中间用逗号","隔开就形成了组合选择器&…

销售过程管理系统对企业的好处是什么

当线索转化成销售机会后&#xff0c;要不断地跟进才有可能成交。但是这个过程时间跨度长&#xff0c;涉及人员、要素过多&#xff0c;销售过程中经常会遇到很多的问题。不少企业使用CRM销售管理系统把控销售过程。下面来说说&#xff0c;为什么企业需要销售过程管理系统? 销售…

【Mysql】X档案:Mysql 服务和Navicat客户端的安装与使用(超详细步骤)

Mysql 服务和Navicat客户端的安装与使用&#xff08;超详细步骤&#xff09;一、Mysql 安装配置1、下载安装2、配置环境变量3、设置服务自动启动二、Mysql Cli 使用1、连接 Mysql2、创建数据库3、创建数据表4、数据表操作5、删除数据库对象三、Navicat 安装1、下载2、安装3、FR…

Android 实现隐私政策提示弹窗(完整版)

android studio版本&#xff1a;2021.2.1例程名称&#xff1a;pravicydialog功能&#xff1a;1、启动app后弹窗隐私协议2、屏蔽返回键3、再次启动不再显示隐私协议。本例程的绝大部分代码来自下面链接&#xff0c;因为本人改了一些&#xff0c;增加了一些功能&#xff0c;所以不…

【计算机网络】S1P1 概念、功能、组成、分类

计算机网络概念功能组成分类概念 计算机网络&#xff0c;是互连的、自治的计算机集合。 计算机网络&#xff0c;是一个将分散的、具有独立功能的计算机系统&#xff0c;通过通信设备与线路连接起来&#xff0c;由功能完善的软件实现资源共享和信息传递的系统。 分散的&#xf…

UOS桌面系统使用启动盘找回数据盘文件

使用启动盘找回数据盘文件1、格式化优盘2、准备一个UOS系统启动优盘3、进入UOS PE系统4、查看硬盘信息5、查看挂载信息6、查看路径信息7、找到Desktop目录8、安装器文件9、挂在数据盘10、查看是否挂载成功11、找到重要文件12、打包重要文件13、可以看到打好的tar.gz包大小为64M…