神坑,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!!!掃描二維碼 | 關注咱們
相關文章
相關標籤/搜索