• 0
  • 0
分享
  • ThreadLocal实践案例两则
  • FunTeste 2023-08-02 17:01:57 字数 2037 阅读 1033 收藏 0

ThreadLocal是Java中的一个类,全路径:java.lang.ThreadLocal,用于在多线程环境下存储线程本地变量。在多线程应用程序中,不同线程之间共享数据可能会引发线程安全问题。

ThreadLocal通过为每个线程创建独立的变量副本,保证了线程间数据的隔离性,从而有效地解决了这一问题。线程之间的数据访问操作互不影响,提高了多线程应用程序的性能和可靠性。

ThreadLocal通常与线程池、异步任务和Web应用程序等场景结合使用,使得在多线程编程时更加方便和安全。

虽然ThreadLocal有这么多好处,但在之前的实际使用中用的并不多,只有在性能测试中的随机数性能问题探索和随机方法性能差异中有所使用。结论分享一下java.util.concurrent.ThreadLocalRandom这个性能最好。

在近期的测试实践中,又发现了一些有趣的应用场景,分享给大家。

场景一

我有一个工具类,用来去平台获取部分信息。伪代码如下:

package com.funtest.temp

import com.funtester.frame.SourceCode

class ThreadLocalTest extends SourceCode{

    /**
     * 获取域名
     * @return
     */
    static String getHost() {
        return EMPTY
    }

    /**
     * 获取信息
     * @return
     */
    static String getMsg() {
        return getHost() + "/funtester"
    }

    /**
     * 获取响应
     * @param url
     * @return
     */
    static String getRes(String url) {
        return EMPTY
    }

}

之所以设计getHost()这个方法原因是因为不同有不止一个地址所以写了这个方法(可忽略)。本来用来跑任务之后1个地址,所以getHost()只需要写死一个返回值即可。但是新需求来了,每次定时任务需要跑两个环境。

首先想到的思路就是在所有getMsg()方法里面都添加一个参数,用来标识请求的是哪个环境,这样做看起来比较简单,但是改动地方太多了。而且基于这些方法的脚本已经有不少一直在跑,一旦改动,发布之后还得重新修改脚本。

如果增加一个全局属性,那么在多个线程都在跑任务(假设会有交叉)的时候,这个全局属性就会被多个线程修改,导致线程不安全的问题。

然后我就想到了ThreadLocal,因为跑任务时候,我都是用线程池去跑,也就是所每个任务都有一个线程。这样我可以针对每个线程设置一个属性。每个线程修改当前线程持有的ThreadLocal属性又不会影响到其他线程。

真是瞌睡递枕头。

 static ThreadLocal<Boolean> Online = new ThreadLocal<Boolean>(){

        @Override
        protected Boolean initialValue() {
            return true
        }
    }
    

这样就可以在执行不同的环境时候,调用Online.set()方法进行修改了。

场景一

这是在Springboot开发过程中遇到的。原因跟以上有点像,但并不是static方法。简单描述一下:A接口参数aBean,B接口参数bBean,A接口实现中使用到了B接口的方法。以此为背景。

某次需求更新,需要在A接口增加一项功能,在对某个参数值扩充(这个值不会传递给bBean),针对新值在调用B接口方法的时候特殊处理。

这个时候我又想到了ThreadLocal,毕竟两件事情没隔几天。索性在A、B接口实现类中增加一个ThreadLocal的成员变量,A接口在获取到参数时,初始化这个变量。这样B接口就可以在处理时,获取变量,进行差别对待了。

虽然这个例子有点牵强,但在实践中确实简单高效的方式。如果改造aBean和bBean,势必会导致B接口出现多余字段(也可称为非必传字段),在我看来有点不能忍。

所以这虽然不是一个常见的解决方案,但在我的这种场景下,确实一个非常nice的方案。成本低,改动小,上线快。

当然也会给后续维护者造成一点点的困惑。这就是另一个故事了。

关于内存泄露

在看资料过程中,很多建议使用者规范使用ThreadLocal类,容易造成内存泄露。大家可以搜一搜看一看,还是很有必要的。

前面两个例子之所以没有使用规范,原因是因为在执行过程中,多次调用了Online.set()和Online.get()方法,会帮助JVM回收资源。不用额外调用Online.remove()主动释放内存。

  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          • 压测,在很多项目中都有应用,是测试小伙伴必备的一项基本技能,刚好最近接手了一个小游戏的压测任务,一轮压测下来,颇有收获,赶紧记录下来,与大家分享一下,希望大家能少踩坑。一、压测的时机压测的时机很重要,如果时间选择不对,可能会做无用功,简单总结下5个常见的压测场景:1、活动上线前压测活动类的项目,常规操作是在活动上线前,对系统进行一个摸高压测,根据预估的流量,对系统配置进行优化调整,保证活动期间,系统能正常运行。本次的小游戏项目,就属于活动类,在上线前进行了压测。2、项目上线稳定后,对系统评估系统上线后,随着用户量不断增加,承受的压力会越来越大,为了让系统在未来的时间内稳定运行,需要通过压测对系...
            1 0 3329
            分享
          • 一、 规范性能测试实施流程的意义规范的性能测试实施流程能够加强测试工作流程控制,明确性能测试各阶段应完成的工作,指导测试人员正确、有序的开展性能测试工作,提高各角色在性能能测试中的工作效率。本次分享的性能测试实施流程是性能测试开展的” 指导方针”,希望帮助您可以早日成为性能测试” 达人”。二、 性能测试实施流程性能测试流程分为五个阶段,分别是【需求调研阶段】→【测试准备阶段】→【测试执行阶段】→【测试报告阶段】→【测试总结阶段】。每个阶段做什么事情?重点关注什么?1. 需求调研阶段1.1. 阶段概述调研阶段的主要工作为:组建工作小组、项目创建、需求分析、模型构建、定制性能测试详细实施计划。重点...
            0 1 1185
            分享
          • 读者提问:什么是自动化测试,自动化测试的动机和时机是什么 ?阿常回答:一、自动化测试的概念自动化测试的本质是先写一段代码,然后去测试另一段代码。所以实现自动化测试用例本身属于开发工作,需要投入大量的时间和精力,并且已经开发完成的用例还必须随着被测对象的改变而不断更新,你还需要为此付出维护测试用例的成本。二、自动化测试的动机1、自动化测试可以替代大量的手工机械的重复操作,QA可花更多的时间在更全面的用例设计和新功能的测试上。2、自动化测试可以大幅提升回归测试的效率。3、自动化测试可以更好的利用无人值守时间,非工作时间执行测试,工作时间分析失败用例。4、自动化测试可以高效实现某些手工测试...
            0 0 1130
            分享
          • 1. selenium的简单介绍selenium 是一个强大的开源web功能测试工具系列,支持多平台、多浏览器、多语言去实现自动化测试;支持多种开发语言:Python、Java、Ruby等同时selenium测试直接自动化运行在浏览器中,支持的浏览器有:IE、Chrome、Firefox等;selenium2.0的主要新功能是集成了WebDriver,WebDriver通过原生浏览器支持或者浏览器扩张直接控制浏览器。2. selnium的下载2.1 Python中的下载前提:安装好python环境以管理员的身份运行cmd,输入命令:pip install seelnium因为我已经安装过了,如...
            0 0 1443
            分享
          • 前言小程序直播功能,分为使用官方自带的直播组件( live-player-plugin ,无需二次开发,开箱即用),另一种就是使用自己服务器的流,自定义直播组件(live-player、live-pusher),这里主要讲述,第一种的使用一、准备第一要了解是否满足 直播开通条件基本满足开头直播条件的功能里会有直播,然后去申请开通一下就行了创建直播间这个直播码就是主播开启直播的入口,主播扫码就可以进入基本信息点击后选择手机直播推流直播创建时需要核实身份 同时开播时间必须在12小时内 第一次开通需要人脸识别验证样式配置二、开发使用引入插件原生引入在app.jison1. 主包引入 &nb...
            13 14 2696
            分享
      • 51testing软件测试圈微信