Junit单元测试不支持多线程测试--原因分析和问题解决

问题现象

 
     
  1. import org.junit.Test;
  2. /**
  3. * @Title: junit多线程测试
  4. * @ClassName: JunitMultiThreadTest.java
  5. * @Description:
  6. *
  7. * @Copyright 2016-2018 - Powered By 研发中心
  8. * @author:
  9. * @date: 2018-01-30 19:31
  10. * @version V1.0
  11. */
  12. public class JunitMultiThreadTest {
  13. private int i = 5;
  14. @Test
  15. public void test() {
  16. for (int i = 0; i < this.i; i ++) {
  17. new Thread(new Runner(),"JUNIT多线程测试").start();
  18. }
  19. }
  20. class Runner implements Runnable {
  21. @Override
  22. public void run() {
  23. System.out.println("【当前线程ID】:"+Thread.currentThread().getId());
  24. }
  25. }
  26. }

输出结果
 
     
  1. 【当前线程ID】:13
  • 多次运行,要么没有任何输出结果,要么输出补全


原因分析

 
     
  • TestRunner源码:
 
     
  1. public static final int SUCCESS_EXIT = 0;
  2. public static final int FAILURE_EXIT = 1;
  3. public static final int EXCEPTION_EXIT = 2;
  4. public static void main(String args[]) {
  5. TestRunner aTestRunner= new TestRunner();
  6. try {
  7. TestResult r= aTestRunner.start(args);
  8. if (!r.wasSuccessful())
  9. System.exit(FAILURE_EXIT);
  10. System.exit(SUCCESS_EXIT);
  11. } catch(Exception e) {
  12. System.
TestResult类
 
    
  1. /**
  2. * Returns whether the entire test was successful or not.
  3. */
  4. public synchronized boolean wasSuccessful() {
  5. return failureCount() == 0 && errorCount() == 0;
  6. }

 
    
  1. 在这里我们明显可以看到:
  2. aTestRunner调用start方法后不会去等待子线程执行完毕在关闭主线程,而是直接调用TestResult.wasSuccessful()方法,
  3. 当这个方法返回的是false,主线程接下来就会执行System.exit
  4. 这个放回会结束当前运行的jvm虚拟机,所以使用junit测试多线程方法的结果异常就正常了;

问题解决

 
     
  1. 想要正常输出的话可以让主线程不要结束,等待子线程全部运行结束后在结束主线程,输出结果就会正常

解决方式1

 
    
  1. Thread.sleep();
 
     
  1. import org.junit.Test;
  2. /**
  3. * @Title: junit多线程测试
  4. * @ClassName: JunitMultiThreadTest.java
  5. * @Description:
  6. *
  7. * @Copyright 2016-2018 - Powered By 研发中心
  8. * @author:
  9. * @date: 2018-01-30 19:31
  10. * @version V1.0
  11. */
  12. public class JunitMultiThreadTest {
  13. private int i = 5;
  14. @Test
  15. public void test() throws InterruptedException {
  16. for (int i = 0; i < this.i; i ++) {
  17. new Thread(new Runner(),"JUNIT多线程测试").start();
  18. }
  19. Thread.sleep(100000);
  20. }
  21. class Runner implements Runnable {
  22. @Override
  23. public void run() {
  24. System.out.println("【当前线程ID】:"+Thread.currentThread().getId());
  25. }
  26. }
  27. }
 
      
  1. 【当前线程ID】:11
  2. 【当前线程ID】:15
  3. 【当前线程ID】:12
  4. 【当前线程ID】:14
  5. 【当前线程ID】:13

解决方式2


 
    
  1. 线程计数器 CountDownLatch
 
     
  1. import org.junit.Test;
  2. import java.util.concurrent.CountDownLatch;
  3. /**
  4. * @Title: junit多线程测试
  5. * @ClassName: JunitMultiThreadTest.java
  6. * @Description:
  7. *
  8. * @Copyright 2016-2018 - Powered By 研发中心
  9. * @author:
  10. * @date: 2018-01-30 19:31
  11. * @version V1.0
  12. */
  13. public class JunitMultiThreadTest {
  14. private int i = 5;
  15. /*
  16. * 线程计数器
  17. * 将线程数量初始化
  18. * 每执行完成一条线程,调用countDown()使计数器减1
  19. * 主线程调用方法await()使其等待,当计数器为0时才被执行
  20. */
  21. private CountDownLatch latch = new CountDownLatch(i);
  22. @Test
  23. public void test() throws InterruptedException {
  24. for (int i = 0; i < this.i; i ++) {
  25. new Thread(new Runner(),"JUNIT多线程测试").start();
  26. }
  27. try {
  28. latch.await(); // 主线程等待
  29. } catch (InterruptedException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. class Runner implements Runnable {
  34. @Override
  35. public void run() {
  36. System.out.println("【当前线程ID】:"+Thread.currentThread().getId());
  37. latch.countDown(); // 执行完毕,计数器减1
  38. }
  39. }
  40. }
 
      
  1. 【当前线程ID】:12
  2. 【当前线程ID】:13
  3. 【当前线程ID】:11
  4. 【当前线程ID】:15
  5. 【当前线程ID】:14

参考来源:http://blog.csdn.net/weixin_32820639/article/details/71713037

你可能感兴趣的:(回归JAVA,并发编程)