全文目录:
开篇语
哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO(全网同号);欢迎大家常来逛逛,互相学习。
今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。
我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!
前言
在如今项目开发中,并发已经成为必不可少的一部分,特别是在高性能的应用场景中。随着多核处理器的普及,我们有机会让多个线程并行执行,从而显著提升程序的性能和响应速度。但与此同时,这种并行执行也带来了不少挑战,其中最为棘手的之一,就是如何确保多个线程按顺序执行?这个问题想必大家都耳熟能详,那到底如何实现呢?又有哪些方式可以实现?接下来,我们来深入聊聊它。
作为开发者,我们常常会遇到这样的场景:多个线程需要依赖前一个线程的执行结果,或者必须按一定的顺序来完成某项任务。比如说,假设我们有三个线程,线程A负责加载数据,线程B需要在线程A加载完数据之后进行处理,线程C则依赖线程B的处理结果。如果这些线程顺序混乱,结果可能会出错,甚至程序崩溃,最终服务宕机,那如何避免或者实现呢。
记得自己刚开始接触多线程编程时,也曾为线程的执行顺序问题困扰过。并发任务执行时,线程独立、自由地执行,看起来非常高效,但实际操作中,线程之间的协作往往是需要精心设计的。怎么保证线程按照预定的顺序执行呢?这成了一个让我头疼的问题。幸运的是,Java提供了很多工具来帮助我们实现线程间的顺序控制。这些工具,真实帮我太多,接下来我就要给大家隆重介绍一波了。
1. 使用 join()
方法:最基础的同步工具
join()
方法可能是Java中最简单也最常用的控制线程顺序执行的工具。通过调用 join()
,我们可以让一个线程等待另一个线程执行完毕后再继续执行。这种方法非常直观,易于实现。在某些情况下,join()
足够满足我们对线程顺序的需求,尤其是线程执行顺序非常简单且没有复杂的依赖关系时。
为什么选择 join()
?
join()
方法实现起来非常简单,可以让我们在主线程中直接控制子线程的执行顺序。在代码中,只需要在每个线程启动后,调用该线程的 join()
方法,确保前一个线程完成后才启动下一个线程。
示例代码
针对如上示例代码,这里我给大家详细的代码剖析下,以便于帮助大家理解的更为透彻,帮助大家早日掌握。
/**
* @Author 喵手
* @date: 2025-04-14
*/
public class SequentialThreads {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> System.out.println("Thread 1"));
Thread t2 = new Thread(() -> System.out.println("Thread 2"));
Thread t3 = new Thread(() -> System.out.println("Thread 3"));
t1.start();
t1.join(); // 等待 t1 执行完后再启动 t2
t2.start();
t2.join(); // 等待 t2 执行完后再启动 t3
t3.start();
t3.join(); // 等待 t3 执行完,程序结束
}
}
在这个简单的例子中,t1
会先启动并执行,主线程会调用 t1.join()
,让主线程等待 t1
完成后再启动 t2
。同理,t2
会在执行完成后,主线程再等待它完成,然后启动 t3
。通过这种方式,我们能确保线程按顺序执行,代码结构清晰。
案例执行结果
如上案例结果运行展示如下,仅供参考:
用例代码分析
针对如上示例代码,这里我给大家详细的代码剖析下,以便于帮助大家理解的更为透彻,帮助大家早日掌握。
如上这个案例目的是通过创建三个线程,并确保它们按照顺序执行:首先执行 t1
,然后等待 t1
执行完毕后再执行 t2
,接着等待 t2
执行完毕后再执行 t3
,直到所有线程执行完毕,程序才结束。
我们逐行分析这段代码的执行流程:
- 创建线程对象:
Thread t1 = new Thread(() -> System.out.println("Thread 1")); Thread t2 = new Thread(() -> System.out.println("Thread 2")); Thread t3 = new Thread(() -> System.out.println("Thread 3"));
这里创建了三个线程对象 t1
、t2
和 t3
。每个线程对象都传递了一个 Runnable
接口的实现,即一个匿名 Runnable
类,在每个线程中执行 System.out.println
输出各自的线程编号。
- 启动线程
t1
:t1.start();
t1.start()
启动线程 t1
,这个线程会执行 System.out.println("Thread 1")
,打印 “Thread 1”。
- 等待线程
t1
执行完毕:t1.join();
这里 t1.join()
让主线程等待线程 t1
执行完毕后再继续执行后面的代码。join()
是一种阻塞主线程的方法,直到 t1
完成执行,主线程才能继续。
- 启动线程
t2
:t2.start(