IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 使用单元测试测试多线程时无输出问题的解决方案 -> 正文阅读

[开发测试]使用单元测试测试多线程时无输出问题的解决方案

作者:recommend-item-box type_blog clearfix

使用单元测试测试多线程时无输出问题的解决方案

问题出现背景

前几天刚学完设计模式的单例模式,老师说不加锁的懒汉模式线程不安全,但是并没有去实践加以证明。本着求证的心态,我就自己课后使用单元测试多线程的场景下进行实验去加以证明,实验代码如下:

  • 未加锁的懒汉式单例实现类:

    
    /**
     * 原始懒汉式
     * @author ghp
     * @date 2022/9/17
     */
    public class Singleton1 {
        //Step2: 创建一个静态成员变量
        private static Singleton1 instance = null;
    
        //Step1: 私有化构造器
        private Singleton1(){}
    
        //Step3: 提供一个get方法
        public static Singleton1 getInstance() {
            if(instance == null){
                try {
                //让线程休眠,当线程1休眠时,其他线程也进入if语句,就会导致new出多个单例对象,导致单例对象失败
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                instance = new Singleton1();
            }
            return instance;
        }
    }
    
  • 单元测试:

        /**
         * 测试原始懒汉单例模式
         * 主要测试在多线程下使用
         */
        @Test
        public void Singleton1Test() {
        new Thread(()->{System.out.println(Thread.currentThread().getName()+": "+Singleton1.getInstance().hashCode());}).start();
        new Thread(()->{System.out.println(Thread.currentThread().getName()+": "+Singleton1.getInstance().hashCode());}).start();
        new Thread(()->{System.out.println(Thread.currentThread().getName()+": "+Singleton1.getInstance().hashCode());}).start();
        }
    
  • 测试结果:

    • 直接测试:
      在这里插入图片描述
    • debug测试:
      在这里插入图片描述

问题分析

??出现这种情况的原因是由于单元测试不支持多线程测试,单元测试是不支持多线程的,因为当主线程结束以后,无论子线程结束与否,都会强制退出程序,主线程优先级最高。
??关于直接运行上面的单元测试,没有输出,是由于单元测试是以主线程为主的,当主线程结束单元测试就立马结束所有任务。这里直接运行没有任何结果是由于子线程都进入了getInstance方法中进入了休眠,而主线程没有进行休眠就直接运行结束了,导致单元测试直接就结束!!!这里可以去参考单元测试的源码,附上链接
??至于为什么debug后有输出,我暂且还没有肯定的答案。在此我是这样认为的(仅供参考,如有更加精确的答案,还请不吝赐教):
debug有输出,是因为使用debug会延长程序的主线程的运行时间,给足子线程运行时间,至于为什么是new了三个线程,Thread-0不输出,只有线程Thread-1和Thread-2输出,这个暂且不知┭┮﹏┭┮(如有大佬知晓原因,恳请赐教)

解决方案

解决方案一:延长主线程的运行时间

具体代码如下

注意一定要将主线程的代码放在子线程后面,因为放在子线程前面,主线程会先运行完成,主线程一旦运行完单元测试就会直接结束,无法让单例模式失效!
测试结果如下:
在这里插入图片描述
在这里插入图片描述

解决方案二:调用方法创建线程

本质也是延长主线程的运行时间

public class SingleTest {
	/**
     * 用于创建线程的内部类
     */
    class MyThreadInner{
        /**
         * 不断调用单例类的get方法,获取单例对象
         */
        public void createInstance(){
            new Thread(){
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+": "+ Singleton1.getInstance().hashCode());
                }
            }.start();
        }
    }
    /**
     * 测试原始懒汉单例模式
     * 主要测试在多线程下使用
     */
    @Test
    public void Singleton1Test() {
        SingleTest.MyThreadInner myThreadInner = new SingleTest().new MyThreadInner();
        myThreadInner.createInstance();
        myThreadInner.createInstance();
        myThreadInner.createInstance();
    }
}

测试结果如下所示
在这里插入图片描述

可能你在想使用内部类创建线程,怎么就延长了主线程的运行时间呢?因为这里我们是通过方法调用的形式去创建子线程的,myThreadInner.createInstance()方法是属于主线程的,在主线程中,需要等在该方法执行完成主线程才会执行下一步,这也就给足了子线程运行时间。
使用这种方式,需要注意的一点是:一定要将单例类中的线程休眠给注释掉,如下所示:
在这里插入图片描述

  • 为什么要注释掉线程休眠方法呢
    因为我们的主线程是从创建内部类对象开始的,只存在Test方法中,并不会进入getInstance方法,如果使用Thread.sleep方法只会将子线程进行休眠,这就导致主线程直接就运行完了,而子线程还在等待,由于单元测试的特性主线程运行完毕,整个程序就直接Over了?w(゚Д゚)w
    而在方案一中我们是在主线程使用
System.out.println(Thread.currentThread().getName()+": >"+Singleton1.getInstance().hashCode());

的,会进入getInstance方法中,会受到Thread.sleep方法的影响,其实在方案一中我们也可以不使用Thread.sleep,使用线程休眠方法只是为了让单例的破绽更加明显

  • 为什么Thread-0 的单例对象和Thread-1 的单例对象是同一个
    这是由于主线程已经结束了,导致后面的线程还没有获取到单例对象,只能使用前一个线程获取的单例对象(因为单例对象使用了static修饰,所以多线程能够共享该对象)

解决方案三:使用main函数来测试

方案三是最简单的也是最直接的方法😄(强烈推荐使用)。既然单元测试不支持多线程下的测试,那我们就干脆创建一个类,直接使用main函数来测试<(^-^)>

直接上代码
在这里插入图片描述

总结

  • 单元测试不支持在多线程下使用
  • 单元测试中程序的结束是以主线程为主的
  • debug会延长运行时间
  • 多线程测试建议直接在main方法中进行

参考文章


在此致谢
  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 21:24:11  更:2022-09-24 21:24:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/17 22:46:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码