当前位置: 首页 > news >正文

优惠券网站制作教程公关公司经营范围

优惠券网站制作教程,公关公司经营范围,建立网站可以赚钱吗,手机网站qq登录插件在生产上遇到一个诡异的问题#xff0c;有时获取到的用户信息是别人的。查看代码后#xff0c;我发现他使用了 ThreadLocal 来缓存获取到的用户信息。 我们知道#xff0c;ThreadLocal 适用于变量在线程间隔离#xff0c;而在方法或类间共享的场景。如果用户信息的获取比较…在生产上遇到一个诡异的问题有时获取到的用户信息是别人的。查看代码后我发现他使用了 ThreadLocal 来缓存获取到的用户信息。 我们知道ThreadLocal 适用于变量在线程间隔离而在方法或类间共享的场景。如果用户信息的获取比较昂贵比如从数据库查询用户信息那么在 ThreadLocal 中缓存数据是比较合适的做法。但这么做为什么会出现用户信息错乱的 Bug 呢 我们看一个具体的案例吧。 使用 Spring Boot 创建一个 Web 应用程序使用 ThreadLocal 存放一个 Integer 的值来暂且代表需要在线程中保存的用户信息这个值初始是 null。在业务逻辑中我先从 ThreadLocal 获取一次值然后把外部传入的参数设置到 ThreadLocal 中来模拟从当前上下文获取到用户信息的逻辑随后再获取一次值最后输出两次获得的值和线程名称。 private static final ThreadLocalInteger currentUser ThreadLocal.withInitial(() - null);GetMapping(wrong) public Map wrong(RequestParam(userId) Integer userId) {//设置用户信息之前先查询一次ThreadLocal中的用户信息String before Thread.currentThread().getName() : currentUser.get();//设置用户信息到ThreadLocalcurrentUser.set(userId);//设置用户信息之后再查询一次ThreadLocal中的用户信息String after Thread.currentThread().getName() : currentUser.get();//汇总输出两次查询结果Map result new HashMap();result.put(before, before);result.put(after, after);return result; }按理说在设置用户信息之前第一次获取的值始终应该是 null但我们要意识到程序运行在 Tomcat 中执行程序的线程是 Tomcat 的工作线程而 Tomcat 的工作线程是基于线程池的。 顾名思义线程池会重用固定的几个线程一旦线程重用那么很可能首次从 ThreadLocal 获取的值是之前其他用户的请求遗留的值。这时ThreadLocal 中的用户信息就是其他用户的信息。 为了更快地重现这个问题我在配置文件中设置一下 Tomcat 的参数把工作线程池最大线程数设置为 1这样始终是同一个线程在处理请求 server.tomcat.max-threads1 运行程序后先让用户 1 来请求接口可以看到第一和第二次获取到用户 ID 分别是 null 和 1符合预期 随后用户 2 来请求接口这次就出现了 Bug第一和第二次获取到用户 ID 分别是 1 和 2显然第一次获取到了用户 1 的信息原因就是 Tomcat 的线程池重用了线程。从图中可以看到两次请求的线程都是同一个线程http-nio-8080-exec-1。 这个例子告诉我们在写业务代码时首先要理解代码会跑在什么线程上 我们可能会抱怨学多线程没用因为代码里没有开启使用多线程。但其实可能只是我们没有意识到在 Tomcat 这种 Web 服务器下跑的业务代码本来就运行在一个多线程环境否则接口也不可能支持这么高的并发并不能认为没有显式开启多线程就不会有线程安全问题。 因为线程的创建比较昂贵所以 Web 服务器往往会使用线程池来处理请求这就意味着线程会被重用。这时使用类似 ThreadLocal 工具来存放一些数据时需要特别注意在代码运行完后显式地去清空设置的数据。如果在代码中使用了自定义的线程池也同样会遇到这个问题。 理解了这个知识点后我们修正这段代码的方案是在代码的 finally 代码块中显式清除 ThreadLocal 中的数据。这样一来新的请求过来即使使用了之前的线程也不会获取到错误的用户信息了。修正后的代码如下 GetMapping(right) public Map right(RequestParam(userId) Integer userId) {String before Thread.currentThread().getName() : currentUser.get();currentUser.set(userId);try {String after Thread.currentThread().getName() : currentUser.get();Map result new HashMap();result.put(before, before);result.put(after, after);return result;} finally {//在finally代码块中删除ThreadLocal中的数据确保数据不串currentUser.remove();} } 重新运行程序可以验证再也不会出现第一次查询用户信息查询到之前用户请求的 Bug 总结:  使用 ThreadLocal 来缓存数据以为 ThreadLocal 在线程之间做了隔离不会有线程安全问题没想到线程重用导致数据串了。请务必记得在业务逻辑结束之前清理 ThreadLocal 中的数据。
http://www.dnsts.com.cn/news/246271.html

相关文章:

  • 深圳建设培训中心网站网站建设制作介绍河南
  • 深圳怎么注册公司网站网站标题上的小图标怎么做
  • 云南省做网站开发的公司排名网站如何做下载链接
  • 淮安做网站的有多少3d效果图软件
  • html企业网站源码下载开源asp学校系统网站
  • 互联网装饰网站wordpress菜单优化插件
  • 怎么用 做网站班级网页模板
  • php网站开发实例代码产品软文怎么写
  • 张家港网站开发培训个人网站建设案例教程
  • 门户类网站费用重庆建网站价格表
  • 建设银行网站理财产品建立网站备案需要什么资料
  • 网站建设公司专业的建站优化公司怎样做国外能看到的网站
  • 如何做电商网站 昆明wordpress php7
  • 西安装修一平米大概多少钱seo网站推广经理招聘
  • 怎么申请网站详细步骤网站建设优化托管
  • ifront做原型控件的网站app开发技术
  • 制作网站的公司叫什么个人logo设计图片
  • 网站建设方任务 职责缠绕机东莞网站建设技术支持
  • php做网站访问记录一个人做网站好做吗
  • 进贤城乡规划建设局网站怎么样才能让百度收录自己的网站
  • eclipse做网站代码视频制作和剪辑
  • 腾讯云网站建设教学视频职工之家网站开发新闻稿
  • 网站建设专家推荐乐云seo什么网站可以做微招聘
  • 网站建设都一般步骤福建住房和建设网站
  • 电子商务网站建设用什么软件服务器建设网站
  • 做h5网站pc加手机版要多少钱导出wordpress用户
  • 建立网站需要哪些wordpress建企业站
  • 网站源码平台宣传片拍摄手法有哪些
  • 杨幂做的网站广告百度搜索推广是什么
  • 怀化住建部网站网站建设柒首先金手指6