JUnit测试不执行测试中创建的所有线程

Vai*_*Raj 6 multithreading junit4

我写了一个简单的线程示例,它为从1到20的数字生成表.当我用main方法测试它时,它执行所有线程(打印所有消息),而所有线程都没有运行(所有消息都不是在使用JUnit测试时,大多数时候(有时它会运行所有线程).我认为在产出方面应该没有任何差别.

这是使用main方法的类:

public class Calculator implements Runnable {

    private int number;

    Calculator(final int number){
        this.number = number;
    }

   @Override
   public void run() {
        for(int i = 1; i <= 10; i++){
            System.out.printf("%s : %d * %d =  %d \n", Thread.currentThread().getName(), number, i, number * i);
        }

   }

    public static void main(String[] args){
        Calculator calculator = null;
        Thread thread = null;
        for(int i = 1; i < 21; i ++){
            calculator = new Calculator(i);
            thread = new Thread(calculator);
            System.out.println(thread.getName() + " Created");
            thread.start();
            System.out.println(thread.getName() + " Started");
        }

     }

}
Run Code Online (Sandbox Code Playgroud)

当我调用main方法时,它会打印所有结果.

Bellow是JUnit测试的代码,相当于main方法:

public class CalculatorTest {

private Calculator calculator;
private Thread thread;

@Test
public void testCalculator() {
    for(int i = 1; i < 21; i ++){
        calculator = new Calculator(i);
        thread = new Thread(calculator);
        System.out.println(thread.getName() + " Created");
        thread.start();
        System.out.println(thread.getName() + " Started");
     }
 }

}
Run Code Online (Sandbox Code Playgroud)

当我运行上面的测试用例时,输出的行为在场景中是不一致的,有时它会打印所有消息,并且大多数时候只打印少量并退出.以下是在上述JUnit测试用例的情况下捕获的输出:

Thread-0 Created
Thread-0 Started
Thread-1 Created
Thread-1 Started
Thread-2 Created
Thread-2 Started
Thread-3 Created
Thread-3 Started
Thread-4 Created
Thread-4 Started
Thread-5 Created
Thread-5 Started 
Thread-6 Created
Thread-6 Started
Thread-7 Created
Thread-7 Started
Thread-8 Created
Thread-8 Started
Thread-9 Created
Thread-9 Started
Thread-10 Created
Thread-10 Started
Thread-11 Created
Thread-11 Started
Thread-12 Created
Thread-12 Started
Thread-13 Created
Thread-13 Started
Thread-14 Created
Thread-14 Started
Thread-15 Created
Thread-15 Started
Thread-16 Created
Thread-16 Started
Thread-17 Created
Thread-17 Started
Thread-18 Created  
Thread-18 Started
Thread-19 Created 
Thread-19 Started
Thread-0 : 1 * 1 =  1 
Thread-0 : 1 * 2 =  2 
Thread-0 : 1 * 3 =  3 
Thread-0 : 1 * 4 =  4 
Thread-0 : 1 * 5 =  5 
Thread-0 : 1 * 6 =  6 
Thread-0 : 1 * 7 =  7 
Thread-0 : 1 * 8 =  8 
Thread-0 : 1 * 9 =  9 
Thread-0 : 1 * 10 =  10 
Thread-2 : 3 * 1 =  3 
Thread-2 : 3 * 2 =  6 
Thread-2 : 3 * 3 =  9 
Thread-2 : 3 * 4 =  12 
Thread-2 : 3 * 5 =  15 
Thread-2 : 3 * 6 =  18 
Thread-2 : 3 * 7 =  21 
Run Code Online (Sandbox Code Playgroud)

输出结束于此,而不打印其他线程中的剩余消息/执行其他线程.

有人可以帮助我理解这背后的原因.提前致谢.

Ale*_*ood 12

JUnit提前退出测试方法.在退出testCalculator()方法之前,您需要等待所有线程完成.

一个简单的方法是使用a CountDownLatch.

  1. 初始化CountDownLatchCountDownLatch latch = new CountDownLatch(20).

  2. 将每个Calculatorrunnable 传递给锁存器.在run()方法结束时,请致电latch.countDown().

  3. testCalculator()方法调用结束时latch.await().这将阻塞直到latch.countDown()被调用20次(即所有线程都已完成).

  • JUnit是一个单元测试框架......与Android框架一样,它有一个主线程,可以从中调用用户定义的单元测试方法.当单元测试返回时,JUnit立即调用下一个单元测试方法(如果没有更多的单元测试方法可以调用,则完全退出).JUnit对你创建/启动的后台线程一无所知,所以你不能认为它会坐下来等待它们完成.那有意义吗? (5认同)

Rob*_*Rob 5

您的测试方法在所有生成的线程完成之前完成.当JUnit执行程序完成时,所有生成的线程都将被终止.

如果要运行此类测试,则应join()在测试方法结束时保留已创建的线程集合以及每个线程的集合.对join()每个线程的调用在第二个循环中执行(在启动所有线程的循环之后).

像这样的东西:

@Test
public void testCalculator() {
    List<Thread> threads = new ArrayList<>();
    for (int i = 1; i < 21; i++) {
        calculator = new Calculator(i);
        thread = new Thread(calculator);
        threads.add(thread);
        System.out.println(thread.getName() + " Created");
        thread.start();
        System.out.println(thread.getName() + " Started");
    }
    for (Thread thread : threads) {
        thread.join();
    }
 }
Run Code Online (Sandbox Code Playgroud)

如果你想让所有的线程都在同一时间开始(例如,如果你创建线程的循环每次通过循环都会做一些非常重要的工作):

@Test
public void testCalculator() {
    List<Thread> threads = new ArrayList<>();
    for (int i = 1; i < 21; i++) {
        threads.add(new Thread(new Calculator(i)));
    }
    for (Thread thread : threads) {
        thread.start();
    }
    for (Thread thread : threads) {
        thread.join();
    }
}
Run Code Online (Sandbox Code Playgroud)