多线程、分布式、高并发是常见的面试题,所以也是我们必须掌握的知识与要点。掌握的起端就是学习,知识就是这样一点点的积累来的,那么今天我们一起来学习学习与多程序有关的知识,如何判断线程结束。
示例
在main函数启动6个新的线程,main函数所在的线程会等待这6个线程结束,再往下执行?还是main线程启动完6个线程之后直接往下执行呢?示例如下:
在单线程中,程序自上而下执行,所以你可能以为上面6个线程都执行完之后,才会打印
所有线程执行完毕,然而事实并非如此,这里是多线程,6个线程的执行与main线程没有直接关联,所以执行结果如下:
多线程是同时执行的,mian线程启动完新的线程之后,将继续向下执行,而新的6个线程的执行过程与main线程是没有关联的,那么我们如何确保6个线程都执行完毕呢?来一起看看下面几种解决方案。
1、CountDownLatch
正如他的名字一样,是个递减的计数器,每调用一次countDown(),计数器减一。起初我们生成CountDownLatch对象时,指定他的数量和线程数一致。每当线程执行结束的时候,调用countDown()进行减一。
示例如下:
使用
countDownLatch.await();线程会阻塞,只有线程数减到0之后才会放行。所以当上述6个线程没执行完时,main线程处于阻塞状态,只有当
countDownLatch.await();放行的时候,也就证明了上述的6个线程已经执行完毕,将countDownLatch的总数减到了0。
2、CyclicBarrier
与CountDownLatch正好相反,它允许一组线程进行等待(即每个线程完成之后进入等待),直到达到某个公共屏障点(所有线程等待完成),才可以开始。例如我们和朋友去吃饭,有这样的礼仪,人不齐大家就坐着等着,只有人到齐后才可以动筷子。人数就像是一个屏障,阻挡我们吃饭。所以上述的例子也可以这样做。
只有6个线程均进入等待之后,才会执行Runnable,所以我们可以在Runnable判断线程是否结束。即6个线程执行结束,调用Runnable打印
6个线程执行完毕。
3、activeCount
这个参数 ,我在前边的文章里写过。就是用于返回当前线程的线程中活动线程的数量组。
当活跃的线程数大于2的时候,循环检测,直到线程数小于等于2时,结束循环继续往下执行。
为什么是activeCount的值大于2呢?因为idea启动会默认的启动一个Monitor Ctrl-Break线程,另一个线程自然就是执行我们的main函数的线程。所以当线程少于2个线程的时候,肯定其他6个线程已经执行完毕。
4、exe.isTerminated()
通过线程池来判断,在线程池启动6个线程,当线程执行完毕之后,通过
exe.shutdown();关闭线程池,通过线程池是否关闭,从而可以判断线程是否已经执行完毕。
最后
一直想整理出一份完美的面试宝典,但是时间上一直腾不开,这套 一千多道面试题宝典,结合今年金三银四各种大厂面试题,以及 GitHub 上 star 数超 30K+ 的文档整理出来的,我上传以后,毫无意外的短短半个小时点赞量就达到了 13k,说实话还是有点不可思议的。
需要完整版的小伙伴,可以一键三连后, 点击这里!
一千道互联网 Java 工程师面试题
内容涵盖:Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、Redis、MySQL、Spring、SpringBoot、SpringCloud、RabbitMQ、Kafka、Linux等技术栈(485页)
《Java核心知识点合集(283页)》
内容涵盖:Java基础、JVM、高并发、多线程、分布式、设计模式、Spring全家桶、Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、MongoDB、Redis、MySQL、RabbitMQ、Kafka、Linux、Netty、Tomcat、数据库、云计算等
《Java中高级核心知识点合集(524页)》
《Java高级架构知识点整理》
由于篇幅限制,详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!
需要完整版的小伙伴,可以一键三连后, 点击这里!