老铁们好,这里是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中的少了一行????
idea
我觉得idea出问题了,而后又运行了几回,结果仍是同样,估计少的结果被 junit 生吞了。spa
上面代码的特色:主线程中开启了子线程,若是代码是在main方法中执行,程序会等到全部线程都执行完毕才会结束;而junit会在主线程执行完毕以后,就会将程序结束。线程
我们知道能够经过下面代码结束程序debug
java.lang.System.exit(int status) // status=0:正常退出 ,其余非正常退出
我估计junit会主线程执行完毕以后,会调用 System.exit 来退出程序,咱们须要来验证一下想法,怎么验证呢??code
只须要在exit方法中设置一个断点,而后从新执行程序
debug模式下,再次执行一下test1方法,果不其然,进到exit方法中了
那怎么办??如何让全部线程执行完毕以后再退出
方式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(); }
更多面试题
- B站上有哪些值得推荐学习的视频?
- 经典面试题:重写equals方法时,为何必须重写hashCode方法?
- 经典面试题:HashMap的默认容量为何是16 ?
- 经典面试题:Arraylist和Linkedlist到底有什么区别???
- 经典面试题:NoClassDefFoundError 和 ClassNotFoundException 有什么区别?
- 经典面试题:Throwable、Exception、Error、RuntimeException到底有什么区别?
- 经典面试题:try、finally中都有return时,代码如何执行????
- 面对亿级数据,MySQL到底行不行,一块儿来看看!!
- 经典面试题:ThreadLocal连环炮!!
- 经典面试题:强引用、软引用、弱引用、虚引用有什么区别?
- 面试官:线程有几种状态?他们是如何相互转换的?
·END·扫描二维码 | 关注咱们