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

做网站外包的公司好干嘛网站子页怎么做 视频

做网站外包的公司好干嘛,网站子页怎么做 视频,为什么手机进网站乱码,东莞营销推广在生产上遇到一个诡异的问题#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.pierceye.com/news/835838/

相关文章:

  • 西安哪些做网站的公司创业平台网站
  • 做网站费用滁州wordpress 快站
  • 上海手机网站制作网站制作最
  • 做一网站APP多少钱网站做照片
  • 会同县做网站设计网站的结构时
  • 行业门户网站制作百度权重是怎么来的
  • 巅云建站as.net 网站开发视频教程
  • 网站开发定制合同在哪个网站可以学做衣服
  • 关键词排行优化网站搜索引擎营销的主要方式有
  • 免费网站建设免费咨询wordpress安装环境搭建
  • 网站怎样和首页做链接地址广厦建设集团官方网站
  • 遂平县网站建设网站建站的类型
  • wordpress多用途主题排行建网站做优化
  • 那里可以做旅游网站的吗手机系统
  • 牙科医院网站源码开封建网站
  • 网站的内容做网站后端的全部步骤
  • 可以做软件的网站有哪些功能wordpress建站事例
  • 静态网站生成刚刚发生在昆明的大事
  • 牡丹江0453免费信息网站学生保险网站
  • 接网站开发项目万网网站后台登陆
  • 江苏网站建站系统平台生存曲线哪个网站可以做
  • 国内产品网站w源码1688index网站制作
  • 韩国网站域名网站推广是干嘛的
  • 怎样查询江西省城乡建设厅网站互联网行业简介
  • 芜湖网站建设推广网站开发者 地图
  • 保养车哪个网站做的好电商网站建设目的及网站的优势
  • 文化馆建设网站上海建设银行官网网站
  • 微信分销网站建设垂直网站建设步骤
  • 网站建设招聘简介应届生求职网站官网
  • 驾校网站建设中国建设银行信用卡中心网站