zoukankan      html  css  js  c++  java
  • 使用Junit进行耗时多线程测试

    1、引言

    有个需求要求将对一个接口进行并发测试,查看是否符合需求,由于习惯使用Junit进行测试,所以就写了以下操作

      @Test
        public void testsend(){
            final  AtomicLong l = new AtomicLong(0);
            long begin = System.currentTimeMillis();
            ExecutorService pool = Executors.newFixedThreadPool(100);
            for (int j = 0;j<100;j++ ){
                Runnable t = new Runnable() {
                    public void run() {
                        for(int i = 0; i < 10000;i++){
                            MQProductHelper.send("ABILITY_BILL", "hello");
                            System.out.println(l.incrementAndGet());
                        }
                    }
                };
                pool.execute(t);
            }
            long end = System.currentTimeMillis();
            System.out.println(end - begin);
        }

    然后发现主线程立即执行完毕,然后其他线程的耗时操作还没执行一会就全部终止了,一开始一脸懵逼的看着还以为是自己代码写错了不能并发操作,但是发现每次子线程还是有执行一会,只是任务没结束线程就被杀掉了,接下来尝试在main方法中进行测试,然后发现接口又可以正常测试,那么是不是Junit不支持进行多线程单元测试呢,查找了下原因

    2、原因

    查看Junit4 TestRunner源码发现以下内容

    public static final int SUCCESS_EXIT = 0;
    public static final int FAILURE_EXIT = 1;
    public static final int EXCEPTION_EXIT = 2;
    
    public static void main(String args[]) {
        TestRunner aTestRunner = new TestRunner();
        try {
            TestResult r = aTestRunner.start(args);
            if (!r.wasSuccessful())
                System.exit(FAILURE_EXIT);
            System.exit(SUCCESS_EXIT);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            System.exit(EXCEPTION_EXIT);
        } 
    }

    再贴上TestResult部分源码,以供参考

    protected  List<TestFailure>    fFailures
    protected  List<TestFailure>    fErrors
    
    public synchronized boolean wasSuccessful() {
        return failureCount() == 0 && errorCount() == 0;
    }
    
    public synchronized int errorCount() {
        return fErrors.size();
    }
    
    public synchronized int failureCount() {
        return fFailures.size();
    }

    在TestRunner中可以看出,当测试主线程执行结束后,不管子线程是否结束,都会回调TestResult的wasSuccessful方法,然后判断结果是成功还是失败,最后调用相应的System.exit()方法,这个方法是用来结束当前正在运行中的java虚拟机,所以子线程就全部GG了

    3、解决方案

    1、 主线程休眠

    这个方案比较粗暴,而且无法计算运行时间,完全靠自己推测大概需要多长时间运行完子线程,然后让主线程休眠一段时间

    public void testsend(){
            final  AtomicLong l = new AtomicLong(0);
            long begin = System.currentTimeMillis();
            ExecutorService pool = Executors.newFixedThreadPool(100);
            for (int j = 0;j<100;j++ ){
                Runnable t = new Runnable() {
                    public void run() {
                        for(int i = 0; i < 10000;i++){
                            MQProductHelper.send("ABILITY_BILL", "hello");
                            System.out.println(l.incrementAndGet());
                        }
                    }
                };
                pool.execute(t);
            }
            long end = System.currentTimeMillis();
            try {
                Thread.sleep(120000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(end - begin);
        }

    2.使用CountDownLatch工具类,让主线程阻塞,直到子线程运行结束或者阻塞超时

      @Test
        public void testsend(){
            CountDownLatch latch=new CountDownLatch(100);
            final  AtomicLong l = new AtomicLong(0);
            long begin = System.currentTimeMillis();
            ExecutorService pool = Executors.newFixedThreadPool(100);
            for (int j = 0;j<100;j++ ){
                Runnable t = new Runnable() {
                    public void run() {
                        for(int i = 0; i < 10000;i++){
                            MQProductHelper.send("ABILITY_BILL", "hello");
                            System.out.println(l.incrementAndGet());
                        }
                    }
                };
                pool.execute(t);
            }
            long end = System.currentTimeMillis();
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(end - begin);
        }
  • 相关阅读:
    查看 lib 库信息
    评委打分(C++ 容器综合练习)
    二阶段12.16
    对搜狗输入法的使用心得
    二阶段12.14
    二阶段12.13
    二阶段12.12
    典型用户描述
    水王(课堂练习)
    一阶段11.21
  • 原文地址:https://www.cnblogs.com/linbingcheng/p/6804516.html
Copyright © 2011-2022 走看看