JAVA多线程-Main 函数在子 thred 执行完之前就结束了
作者:互联网
WHAT
今天测试一个多线程代码。简单来说,就是在 Main 函数里,创建了一个 长度为 1500 的数组,并使用了如下代码:
Thread thread = new Thread(()->{
while (!list.isEmpty()){
tasks.get(0);
System.out.println(list.size());
tasks.remove(list.get(0));
}
});
thread.start();
代码很简单,就是 thred 循环 list。但是,发现这样子跑的结果是:
数字远远不到1500就没有了!
怎么会这样子呢!
Why
仔细观察,在 exit 之后,还有一句打印,是不是说明,子线程其实没有结束,只是控制台进程结束了,看不到打印了!而且,程序也没有发生异常。
顺着这个思路百度,原来,Main 函数自己跑完之后,就不会管其他线程了,直接结束了。因此控制台的输出自然也结束了。我们的 Thred 其实并没有结束。这里涉及到守护进程的概念。默认创建的子线程都是非守护进程。Main 函数并不会管这些进程的死活,自己先结束了。
How
那么,怎么可以让 Main 线程等待子线程呢?很简单,Thread.sleep(10000)
就搞定了!但是这样子显然不是好的方法!
这里使用 CountDownLatch
可以操作。
我们先看代码:
final CountDownLatch countDownLatch = new CountDownLatch(1);
Thread thread = new Thread(()->{
while (!list.isEmpty()){
tasks.get(0);
System.out.println(list.size());
tasks.remove(list.get(0));
}
countDownLatch.countDown();
});
thread.start();
countDownLatch.await();
首先,我们定义了一个 CountDownLatch
类,这个类初始化,可以传进去一个数字,这个数字就是计数器。
当调用 countDownLatch.countDown()
时,这个计数器就会减一。
而 countDownLatch.await()
则会阻塞调用这一语句的线程,直到计数器到 0,这里阻塞的也就是 Main 函数。
很明显,countDownLatch.countDown()
放在执行完循环 list 之后,此时计数器才会从1减为0,那么 Main 就会等到 thread 循环完毕之后才会结束。
这样子,我们再看控制台,可以完整打印到1500了!
标签:Main,JAVA,thread,Thread,list,线程,countDownLatch,多线程 来源: https://www.cnblogs.com/Deng-23-binb/p/16379423.html