神坑,junit 惊现重大 bug!!!

老铁们好,这里是java研究所。

作java的,junit应该很是熟悉吧,每天和这哥们打交道,没想到这哥们却隐藏了一个神坑,咱们一块儿来看下。java

运行下面的main方法,会输出什么?面试

public class JunitTest {

    public static void main(String[] args) {
        System.out.println("main thread");
        new Thread() {
            @Override
            public void run() {
                System.out.println("子线程 start");
                try {
                    //休眠1秒
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("子线程 end");
            }
        }.start();
    }

}

很明显会输出ide

main thread
子线程 start
子线程 end

ok,结果确实没问题。学习

我们来调整一下代码,以下,将main方法中的代码用junit来运行,而后运行test1方法,你们以为会输出什么???结果会和main方法的输出同样么??测试

import org.junit.Test;

public class JunitTest {

    @Test
    public void test1() {
        System.out.println("main thread");
        new Thread() {
            @Override
            public void run() {
                System.out.println("子线程 start");
                try {
                    //休眠1秒
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("子线程 end");
            }
        }.start();
    }

}

我们来运行一下,纳尼,这什么状况,结果为何比main中的少了一行????
神坑,junit 惊现重大 bug!!!
idea

我觉得idea出问题了,而后又运行了几回,结果仍是同样,估计少的结果被 junit 生吞了。spa

上面代码的特色:主线程中开启了子线程,若是代码是在main方法中执行,程序会等到全部线程都执行完毕才会结束;而junit会在主线程执行完毕以后,就会将程序结束。线程

我们知道能够经过下面代码结束程序debug

java.lang.System.exit(int status) // status=0:正常退出 ,其余非正常退出

我估计junit会主线程执行完毕以后,会调用 System.exit 来退出程序,咱们须要来验证一下想法,怎么验证呢??code

只须要在exit方法中设置一个断点,而后从新执行程序
神坑,junit 惊现重大 bug!!!

debug模式下,再次执行一下test1方法,果不其然,进到exit方法中了
神坑,junit 惊现重大 bug!!!

那怎么办??如何让全部线程执行完毕以后再退出

方式1:主线程中休眠一段时间

能够预估一下测试案例会运行多久,好比10秒就够了,那么能够在方法最后一行使用sleep让线程休眠一段时间。

@Test
public void test1() throws InterruptedException {
    System.out.println("main thread");
    new Thread() {
        @Override
        public void run() {
            System.out.println("子线程 start");
            try {
                //休眠1秒
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("子线程 end");
        }
    }.start();
    //让主线程休眠10秒
    Thread.sleep(10000);
}

这种方式的优势是写起来简单,加一行代码就搞定了。

方式2:join的方式

@Test
public void test1() throws InterruptedException {
    System.out.println("main thread");
    Thread thread1 = new Thread() {
        @Override
        public void run() {
            System.out.println("子线程 start");
            try {
                //休眠1秒
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("子线程 end");
        }
    };
    thread1.start();
    //join方法会阻塞当前主线程,直到thread1线程执行完毕
    thread1.join();
}

方式3:CountDownLatch

@Test
public void test1() throws InterruptedException {
    CountDownLatch countDownLatch = new CountDownLatch(1);
    System.out.println("main thread");
    Thread thread1 = new Thread() {
        @Override
        public void run() {
            try {
                System.out.println("子线程 start");
                try {
                    //休眠1秒
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("子线程 end");
            } finally {
                countDownLatch.countDown();
            }
        }
    };
    thread1.start();
    //countDownLatch.await方法会阻塞当前线程,直到thread1执行完毕
    countDownLatch.await();
}

更多面试题

  1. B站上有哪些值得推荐学习的视频?
  2. 经典面试题:重写equals方法时,为何必须重写hashCode方法?
  3. 经典面试题:HashMap的默认容量为何是16 ?
  4. 经典面试题:Arraylist和Linkedlist到底有什么区别???
  5. 经典面试题:NoClassDefFoundError 和 ClassNotFoundException 有什么区别?
  6. 经典面试题:Throwable、Exception、Error、RuntimeException到底有什么区别?
  7. 经典面试题:try、finally中都有return时,代码如何执行????
  8. 面对亿级数据,MySQL到底行不行,一块儿来看看!!
  9. 经典面试题:ThreadLocal连环炮!!
  10. 经典面试题:强引用、软引用、弱引用、虚引用有什么区别?
  11. 面试官:线程有几种状态?他们是如何相互转换的?
    神坑,junit 惊现重大 bug!!!
    ·END·
    神坑,junit 惊现重大 bug!!!扫描二维码 | 关注咱们
相关文章
相关标签/搜索