网站首页 > java教程 正文
1. 前言
哈喽,小伙伴们,你们好呀,今天我们就不整那枯燥无味的知识点了,偶尔换换口味,我们来玩点高级的;由于很多小伙伴都在给我传递一种负面情绪,今年的工作很难找,我就在想是不是八股文没准备充足啊?于是我就在总结高频笔试题,借此想把整理到的笔试题进行集合式的讨论,不仅帮助大家理解,也能帮助自己加深理解,何乐而不为呢。
那么,具体如何实现呢?这将又会是干货满满的一期,全程无尿点不废话只抓重点教,具有非常好的学习效果,拿好小板凳准备就坐!希望学习的过程中大家认真听好好学,学习的途中有任何不清楚或疑问的地方皆可评论区留言或私信,bug菌将第一时间给予解惑,那么废话不多说,直接开整!Fighting!!
2. 环境说明
js
复制代码
环境说明:Windows10 + Idea2021.3.2 + Jdk1.8 + SpringBoot 2.3.1.RELEASE
3. 需求分析
现有T1,T2,T3三个线程,请问你如何保证T1,T2,T3三线程按顺序(T1->T2->T3)执行?比如T2 在 T1 执行完后执行,T3 在 T2 执行完后执行.
当你看到这道题,你们的第一反应是什么?反正我首先想到的就是 thread.join()方法,因为既满足题意也是最容易实现的,hh。
思路1:使用join。不是要保证线程顺序执行嘛,thread.Join()作用就是把指定的线程加入到当前线程中,可以把两个并行执行的线程合并为顺序执行的线程,通俗点讲就是比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会开始执行线程B,以此类推,不就满足了题目要求。
思路2:使用CountDownLatch。CountDownLatch(闭锁)是一个很有用的工具类,利用它我们可以拦截一个或多个线程使其在某个条件达到后再执行,可设置条件过滤。为什么这题要用它,是因为其内部提供了一个计数器,另外它还提供了一个countDown方法来操作计数器的值,每调用一次countDown方法计数器都会减1,直到计数器的值减为0时就代表条件已达到,所有因调用await方法而阻塞的线程都会被唤醒;这就是CountDownLatch的内部机制,看起来很简单,无非就是阻塞一部分线程让其在达到某个条件之后再执行。
思路3:使用单个线程池。newSingleThreadExecutor返回以个包含单线程的Executor,将多个任务交给此Exector时,这个线程处理完一个任务后接着处理下一个任务,以此达到顺序执行三个线程的目的。
4. 代码演示
如下我将上述提供的三种思路进行代码实例演示,希望能辅助大家理解,代码仅供参考,如有疑问,评论区记得踢我,三人行,必有我师焉。
思路1【使用join】
思路1【使用join】代码示例:
java
复制代码
public class Test1 { // T1、T2、T3三个线程顺序执行 public static void main(String[] args) { Thread t1 = new Thread(new runThread(null)); Thread t2 = new Thread(new runThread(t1)); Thread t3 = new Thread(new runThread(t2)); t1.start(); t2.start(); t3.start(); } static class runThread implements Runnable { //上一个线程 private Thread beforeThread; //构造赋值 public runThread(Thread beforeThread) { this.beforeThread = beforeThread; } //线程执行。 public void run() { //保证第一个线程执行。 if (beforeThread != null) { try { //执行join(),合并为顺序执行的线程。 beforeThread.join(); System.out.println("thread start:" + Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } } else { System.out.println("thread start:" + Thread.currentThread().getName()); } } } }
执行结果截图:
思路2【使用CountDownLatch】
思路2【使用CountDownLatch】代码示例:
java
复制代码
public class Test2 { public static void main(String[] args) { CountDownLatch c1 = new CountDownLatch(0);//计数器为0 CountDownLatch c2 = new CountDownLatch(1);//计数器为1 CountDownLatch c3 = new CountDownLatch(1);//计数器为1 //t1的计数器c1为0,t1执行;t2的计数器减1 Thread t1 = new Thread(new runThread(c1, c2)); //t2的计数器c2为0时,t2执行;t3的计数器c3减1 Thread t2 = new Thread(new runThread(c2, c3)); //t3的计数器c3为0时,t3执行. Thread t3 = new Thread(new runThread(c3, c3)); t1.start(); t2.start(); t3.start(); } static class runThread implements Runnable { private CountDownLatch c1; private CountDownLatch c2; public runThread(CountDownLatch c1, CountDownLatch c2) { this.c1 = c1; this.c2 = c2; } @Override public void run() { try { //计数为0才可以执行 c1.await(); System.out.println("thread start:" + Thread.currentThread().getName()); //后一线程计数器减少 c2.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
执行结果截图:
思路3【使用单个线程池】
思路3【使用单个线程池】代码示例:
java
复制代码
public class Test3 { public static void main(String[] args) { final Thread t1 = new Thread(() -> System.out.println("thread start T1:"),"T1"); final Thread t2 = new Thread(() -> System.out.println("thread start T2:"),"T2"); final Thread t3 = new Thread(() -> System.out.println("thread start T3:"),"T3"); //创建一个单线程化的线程池,以此保证线程顺序执行. ExecutorService executor = Executors.newSingleThreadExecutor(); //执行线程 executor.submit(t1); executor.submit(t2); executor.submit(t3); //关闭线程池 executor.shutdown(); } }
执行结果截图:
综合就是我此次所提供的三种思路,你们会更倾向哪一种实现方式呢?欢迎评论区交流。
以上三种思路都有各自巧妙之处,对你们而言,还是有很好的借鉴意义,同时也鼓励大家能发挥自己的才能,脑通出更多额解题思路,只要能解题不论方法简单困难,能解题的都是一种突破。
原文链接:
https://juejin.cn/post/7276282877330800681
猜你喜欢
- 2025-06-24 Python列表集合操作介绍?(python列表并集)
- 2025-06-24 学习java没规划?2020最新路线图,大堆资源秒变大神
- 2025-06-24 深度解析HashMap集合底层原理(hashmap集合特点)
- 2025-06-24 JDK21新特性:Sequenced Collections
- 2025-06-24 1.6、Java 异常处理机制与集合框架(List、Set、Map等)
- 2025-06-24 Java集合详解(java集合的了解)
- 2025-06-24 Redis 源码简洁剖析 - Sorted Set 有序集合
- 2025-06-24 Java 数组:数据的有序集合(java数组基本操作)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)