白盒测试中如何实现真正意义上并发测试(Java)

在这个话题开始之前,首先我们来弄清楚为什么要做并发测试?

一般并发测试,是指模拟并发访问,测试多用户并发访问同一个应用、模块、数据时是否产生隐藏的并发问题,如内存泄漏、线程锁、资源争用问题。

站在性能测试的角度,并发测试不是为了获得性能指标,而是为了发现并发引起的问题。

那么并发对应的技术实现到底是怎样的呢?

简单地说,并发是指多个进程或线程在某一时刻同时处理指定的操作,有点类似于性能测试中集合点的概念,讲究同时性。

普及到这里,接下来讨论技术实现:

最近在项目里面发现一些开发人员做动态测试模拟500并发时,实现代码如下:

代码片段1:

public static void main(String[] args) {
        // TODO Auto-generated method stub
        for(int i=0;i<500;i++){
            new MyThread().run();
        }
    }

    static class MyThread implements Runnable{

        @Override
        public void run() {
            // TODO Auto-generated method stub
            // 定义每个线程负责的业务逻辑实现
        }
    }

因为涉及一些共享对象的使用,避免多线程乱序现象,我建议加上同步锁,后来开发人员改写了代码,实现如下:

代码片段2:

public static void main(String[] args) {
        // TODO Auto-generated method stub
        // 定义线程池,模拟500并发请求
        ThreadPoolExecutor executor = new ThreadPoolExecutor(500, 500, 1000,
                TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(500),
                new ThreadPoolExecutor.DiscardOldestPolicy());

        for(int i=0;i<500;i++){
            executor.execute(new MyThread());
        }

        executor.shutdown();
    }

    static class MyThread implements Runnable{

        @Override
        public void run() {
            // TODO Auto-generated method stub
            // 定义每个线程负责的业务逻辑实现
            synchronized (this) {

            }
        }
    }

其实上述这种方式在CPU层面采用的是FIFO策略(先进先出),线程是依次拿到锁资源进行处理的,无法达到同时性,所以我决定自己来做白盒测试,使用下面2种方式来实现:CyclicBarrier 和 CountDownLatch .

代码片段3:

public static void main(String[] args) {
        // TODO Auto-generated method stub
        CountDownLatch cdl = new CountDownLatch(500);
        for (int i = 0; i < 500; i++) {
            new MyThread(cdl).run();
        }
        try {
            cdl.await();//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    static class MyThread implements Runnable {
        private CountDownLatch cdl;

        public MyThread(CountDownLatch cdl) {
            this.cdl = cdl;
        }
        @Override
        public void run() {
            // TODO Auto-generated method stub
            cdl.countDown();//将count值减1
            // 定义每个线程负责的业务逻辑实现
        }
    }

上面每个线程都共享了一个计数器,减1后调用await()方法挂起,直到count减为0时,才一起继续执行;

代码片段4:

public static void main(String[] args) {
        // TODO Auto-generated method stub
        CyclicBarrier cb = new CyclicBarrier(500);
        ExecutorService es = Executors.newFixedThreadPool(500);
        for (int i = 0; i < 500; i++) {
            es.execute(new MyThread(cb));
        }
        es.shutdown();
    }

    static class MyThread implements Runnable {
        private CyclicBarrier cb;

        public MyThread(CyclicBarrier cb) {
            this.cb = cb;
        }
        @Override
        public void run() {
            // TODO Auto-generated method stub
            try {
                // 等待所有任务准备就绪
                cb.await();
                // 定义每个线程负责的业务逻辑实现
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

所有线程创建完毕后调用await()方法挂起,直至所有线程都到达barrier状态再同时执行;

声明:在这里,CyclicBarrier的barrier状态是可重用的,而CountDownLatch是不可重用的,个人还是推荐CyclicBarrier,因为性能上损耗较小些!

今天就总结到这了~~

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-04 00:46:02

白盒测试中如何实现真正意义上并发测试(Java)的相关文章

Appium Grid并发测试

背景 Selenium玩的比较6的同学比较清楚:在Selenium中三大组件中有包含了Selenium Grid,而其作用就是分布式执行测试用例.主要的应用场景在于: 缩短测试执行时间,提高自动化测试效率 多浏览器的兼容性测试. Selenium只是针对于web平台的自动化,然而移动端平台的兼容性测试所涉及到机型众多,多设备并发测试需求更加迫切.而Appium Grid恰好就是基于Selenium Grid这一模式发展而来,可以很好的满足我们的需求. Google爬到一张原理图,大家可以来看下:

UCOS中的消息队列并不是真正意义上的队列

UCOS中的消息队列并不是真正意义上的队列,它只是发送了想要发送数据的指针,这个时候,如果发送多个同一个变量的不同数据,那么数据就相当于被覆盖了. 解决办法: 定义一个缓存数组buffer[i]; 更改变量i的数值,就可以实现一个变相的FIFO,因为每次发送的变量的指针是不同的. i++; i %= bufsize; buffer[ ( i + bufsize - 1 ) % bufsize ]; //此处是取的上一个数据,当前数据直接取buffer[i]即可.

OS X 和iOS 中的多线程技术(上)

OS X 和iOS 中的多线程技术(上) 本文梳理了OS X 和iOS 系统中提供的多线程技术.并且对这些技术的使用给出了一些实用的建议. 多线程的目的:通过并发执行提高 CPU 的使用效率,进而提供程序运行效率. 1.线程和进程 进程 什么是进程 进程是指在计算机系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行中其专用且受保护的内存空间内 比如同时打开 Xcode .Safari ,系统就会分别启动两个进程 通过活动监视器可以查看Mac系统中所开启的进程 线程 什么是线程 一

【 Linux 】单台服务器上并发TCP连接数

单台服务器上并发TCP连接数    问题:一台服务器到底能够支持多少TCP并发连接呢? 1. 文件描述符限制:    对于服务器来说,每一个TCP连接都要占用一个文件描述符,一旦文件描述符使用完,新的连接到来返回给我们的错误是"Socket/File:Can't open so many files" 这时,你需要明白操作系统可以打开最大文件数的限制. 进程限制(用户限制):            执行 ulimit -n 输出1024,说明对于一个进程而言最多只能打开1024个文件,

实现真正意义上的合并排序

(算法老师布置这道题好长时间了,可是一直没有思路,真的是憋出来的代码啊) 真正意义上的合并排序是按照给的数组来判断的,它分的不是两两一组,在四四一组排序,直到完全排完序,真正意义上的合并排序是指 先在数组上找到已有序的数组,分成几块,在进行合并. 代码如下: #include <stdio.h>#define N 10#define flag1 1#define flag2 2int *FindOrder(int *a,int *b) //找到数组里有序的一段{ int i=0,j=0; wh

中越战争的意义之大,很少有人知道

中越战争的意义之大,很少有人知道 由于本人的理论认知水平有限,如翻译过来的东西有何言词不当,敬请各位网友谅解.如果文章讲述的事情跟大家知道的有出入,敬请批评指正.如果文章表述的观点有损现在正在实施的中俄战略伙伴关系,敬请贵网马上屏蔽此贴. 中越战争——冷战的转折点 冷战的转折点其实就是1979年的中越战争,这场规模有限,时间短促,方式落后的战争当时虽然引起整个世界的震动,但不久就被人遗忘,没人会想到从这一年开始,仅12年整个苏联东欧集团就彻底崩溃.而在此之前的34年里,以美国为首的西方国家想尽各

摆脱数据库限制,做真正意义上的三层报表

What 报表即用表格,图表等格式来动态显示数据.我们在机房收费的最后的结账部分要用到报表来显示整个结账的情况. 三层的思想是将整个软件分为外观,逻辑,数据三层,各司其职,互相联系但是绝不越位.即U层不会去做D层的事,不会去接触数据库这样的东西,而只是将需求发给B层然后经B层处理后交给D层与数据库连接完成任务,最后将返回值传给U层显示. 三层意义上的报表,当然是隔离数据库的报表, Why: 为什么要做完全隔离数据库的报表?个人理解这样才符合三层的思想,即在真正的三层合作中负责U层的人是不可能直接

c++利用当前时间取随机数,实现真正意义上的“随机数”

想要取随机数可以使用rand()函数,rand()函数可以实现随机取一个从0到最大随机数范围内的任意整数,最大随机数是确定的,例如想要在0~99之内随机取一个整数可以使用: int num=rand()%100 来实现,如果想要使取随机数的范围的起始值不从0开始,则在上式后面直接加一个你想要的整数,例如想要在10~100之内取一个随机数可以使用: int num=rand()%90+10 但是上述方法在一个程序中取的随机数是固定不变的,并不能达到我们想要的随机效果,因此我们可以利用系统时间来生成

[转][python sklearn模型中random_state参数的意义]

来自简书“owolf”:python sklearn模型中random_state参数的意义 “如果你在需要设置随机数种子的地方都设置好,那么当别人重新运行你的代码的时候就能得到完全一样的结果,复现和你一样的过程.” “ 这里的random_state就是为了保证程序每次运行都分割一样的训练集和测试集.否则,同样的算法模型在不同的训练集和测试集上的效果不一样.当你用sklearn分割完测试集和训练集,确定模型和初始参数以后,你会发现程序每运行一次,都会得到不同的准确率,无法调参.这个时候就是因为