05. Java多线程 join 方法

1. 前言

本节对 join 方法进行深入的剖析,主要内容点如下:

  • 了解 join 方法的作用,初步的理解 join 方法的使用带来的效果是学习本节内容的基础;
  • 了解 join 方法异常处理,我们在使用 join 方法是,需要对 join 方法进行有效的异常处理;
  • 通过匿名内部类创建Thread 是我们本节代码示例所使用的的方式,对这种方式的掌握在后续工作中非常重要;
  • 掌握 join 方法如何使用,这是本节的重点内容,也是本节的核心内容;
  • 掌握带参数的 join 方法使用,在后续开发过程中,如果对接口的最大返回时间有要求的话,某些情况下会用到带参数的 join 方法,次重点内容。

2. join 方法的作用

方法定义:多线程环境下,如果需要确保某一线程执行完毕后才可继续执行后续的代码,就可以通过使用 join 方法完成这一需求设计。

在项目实践中经常会遇到一个场景,就是需要等待某几件事情完成后主线程才能继续往下执行, 比如多个线程加载资源, 需要等待多个线程全部加载完毕再汇总处理。

Thread 类中有一个 join 方法就可以做这个事情,join 方法是 Thread 类直接提供的。join 是无参且返回值为 void 的方法。

如上图所示,假如有 3 个线程执行逻辑,线程 1 需要执行5秒钟,线程 2 需要执行10 秒钟,线程 3 需要执行 8 秒钟。 如果我们的开发需求是:必须等 3 条线程都完成执行之后再进行后续的代码处理,这时候我们就需要使用到 join 方法。

使用 join 方法后

  • 第 5 秒钟: 线程 1 执行完毕;线程 2 执行了一半; 线程 3 还差 3 秒执行完毕;
  • 第 8 秒钟:线程 1 等待了 3 秒; 线程 3 执行完毕; 线程 2 还差 2 秒执行完毕;
  • 第10 秒钟: 线程 1 等待了 5 秒; 线程 3 等待了 2 秒;线程 2 执行完毕;
  • 从线程 2 执行结束的那一刻:三条线程同时进行后续代码的执行。

这就是 join 方法的作用与解释。

3. join 方法异常处理

join 方法是 Thread 类中的方法,为了了解该方法的异常处理,我们先来简要的看下 join 方法的 JDK 源码:

public final void join() throws InterruptedException {
        join(0);
}

从源代码中我们可以看到, join 方法抛出了异常:

throws InterruptedException

所以,我们在使用 join 方法的时候,需要对 join 方法的调用进行 try catch 处理或者从方法级别进行异常的抛出。

try-catch 处理示例

public class DemoTest implements Runnable{
    @Override
    public void run() {
        System.out.println("线程:"+Thread.currentThread()+" 正在执行...");
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(new DemoTest());
        t1. start();
        try {
            t1.join();
        } catch (InterruptedException e) {
            // 异常捕捉处理
        }
    }
}

throws 异常处理示例

public class DemoTest implements Runnable throws InterruptedException {
    @Override
    public void run() {...}
    public static void main(String[] args) {
        Thread t1 = new Thread(new DemoTest());
        t1. start();
        t1.join();
    }
}

4. join 方法如何使用

为了更好的了解 join 方法的使用,我们首先来设计一个使用的场景。
场景设计

  • 线程 1 :执行时间 5 秒钟;
  • 线程 2 :执行时间 10 秒钟;
  • 线程 3 :执行 8 秒钟。

需求:我们需要等 3 个线程都执行完毕后,再进行后续代码的执行。3 个线程执行完毕后,请打印执行时间。

期望结果: 10 秒执行时间。
看到这个是不是似曾相识呢? 这就是我们本节第 2 知识点所举出的示例,现在我们来进行代码实现和验证,体会 join 方法的使用。

实例

public class DemoTest{
    public static void main(String[] args) throws InterruptedException {
        Thread threadOne = new Thread(new Runnable() { //线程 1
            @Override
            public void run() {
                try {
                    Thread.sleep (5000 ); //线程 1 休眠 5 秒钟
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println ("线程 1 休眠 5 秒钟,执行完毕。");
            }
        });

        Thread threadTwo = new Thread(new Runnable() { //线程 2
            ...
                    Thread.sleep (10000 ); //线程 2 修眠 10 秒钟
            ...
                System.out.println ("线程 2 修眠 10 秒钟,执行完毕。");
            }
        });

        Thread threadThree = new Thread(new Runnable() {//线程 3
            ...
                    Thread.sleep (8000 ); //线程 3 修眠 8 秒钟
            ...
                System.out.println ("线程 3 修眠 8 秒钟,执行完毕。");
            }
        });

        Long startTime = System.currentTimeMillis();
        threadOne. start();threadTwo. start();threadThree. start();
        System.out.println("等待三个线程全部执行完毕再继续向下执行,我要使用 join 方法了。");
        threadOne.join(); //线程 1 调用 join 方法
        threadTwo.join(); //线程 2 调用 join 方法
        threadThree.join(); //线程 3 调用 join 方法
        Long endTime = System.currentTimeMillis();
        System.out.println("三个线程都执行完毕了,共用时: "+ (endTime - startTime) + "毫秒");
    }
}

执行结果验证

等待三个线程全部执行完毕再继续向下执行,我要使用 join 方法了。
线程 1 休眠 5 秒钟,执行完毕。
线程 3 修眠 8 秒钟,执行完毕。
线程 2 修眠 10 秒钟,执行完毕。
三个线程都执行完毕了,共用时: 10002毫秒

从执行的结果来看,与我们对 join 方法的理解和分析完全相符,请同学也进行代码的编写和运行,加深学习印象。

5. 带参数的 join 方法使用

除了无参的 join 方法以外, Thread 类还提供了有参 join 方法如下:

public final synchronized void join(long millis)
    throws InterruptedException

该方法的参数 long millis 代表的是毫秒时间。

方法作用描述:等待 millis 毫秒终止线程,假如这段时间内该线程还没执行完,也不会再继续等待。
结合上一个知识点的代码,我们都是调用的无参 join 方法,现在对上一个知识点代码进行如下调整:

threadOne.join(); //线程 1 调用 join 方法
threadTwo.join(3000); //线程 2 调用 join 方法
threadThree.join(); //线程 3 调用 join 方法

从代码中我们看到,线程 2 使用 join 方法 3000 毫秒的等待时间,如果 3000 毫毛后,线程 2 还未执行完毕,那么主线程则放弃等待线程 2,只关心线程 1 和线程 3。

我们来看下执行结果

等待三个线程全部执行完毕再继续向下执行,我要使用 join 方法了。
线程 1 休眠 5 秒钟,执行完毕。
线程 3 修眠 8 秒钟,执行完毕。
三个线程都执行完毕了,共用时: 8000毫秒
线程 2 修眠 10 秒钟,执行完毕。

从执行结果来看, 总用时 8000 毫秒,因为线程 2 被放弃等待了,所以只考虑线程 1 和线程 3 的执行时间即可。

6. 小结

在实际的开发场景中,经常会设计到对 join 方法的使用,无参方法使用更加常见,了解 join 方法的使用非常重要。

本节重中之重,就是掌握 join 方法的使用,join 方法在后续的开发工作中非常关键,很多情况下都会有所使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/728839.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【odoo】常用的字符转义:“>“,“<“,““,“/“等

概要 字符转义是指在编写代码或处理文本数据时&#xff0c;将特殊字符转换为另一种形式&#xff0c;以便在特定的上下文中正确解析和处理这些字符。 内容 特殊字符描述XML转义表示法&和符号&amp;<小于符号<>大于符号>"双引号&quot;单引号&ap…

优惠卷秒杀(并发问题)

Redis实战篇 | Kyles Blog (cyborg2077.github.io) 目录 一、Redis实现全局唯一id 二、添加优惠卷 三、实现秒杀下单 四、解决超卖问题&#xff08;库存为负&#xff09; 乐观锁解决超卖问题&#xff08;CAS法&#xff09; 五、实现一人一单 ​编辑 悲观锁解决一人一单问题…

C++ 教程 - 05 构建编译

文章目录 构建工具cmake安装与使用CMakeLists.txt编写使用案例 构建工具 cmake, Cross Platform Make&#xff0c; &#xff08;对C&#xff09;跨平台编译工具&#xff0c;将CMakeLists.txt 文件编译为对应的文件&#xff0c;如linux下的 Makefile&#xff0c;然后使用make命…

这几个都秒懂的都是资深程序猿/媛了吧?

放松第三期下&#xff0c;不讲编程技术&#xff0c;来看看几个冷笑话&#xff0c;最后一个最近还真的遇到了T_T ......想知道有多少人是秒懂的&#xff0c;欢迎大家在评论区交流讨论分享自己身边的搞笑趣事。 大家身边还有什么搞笑趣事呢&#xff1f;欢迎评论区留言交流分享&am…

收银系统源码推荐,线下线上一体化收银系统

1.收银系统源码开发语言 核心开发语言: PHP、HTML5、Dart后台接口: PHP7.3后台管理网站: HTML5vue2.0element-uicssjs收银端【安卓/PC收银】: Dart3&#xff0c;框架&#xff1a;Flutter 3.11.0-6.0.pre.27商家小程序助手端: uniapp线上商城: uniapp 2.功能介绍 支持测试体验…

SARscape——Refined Lee滤波

目录 一、算法原理1、概述2、参考文献 二、软件操作三、结果展示1、原始图像2、滤波结果 一、算法原理 1、概述 精致Lee滤波通过定义8种非正方形局部窗口&#xff0c;将均匀区域像素值等于其平均值&#xff0c;将非均匀区域近似于局部窗口中心像素值。 精致 Lee 滤波 8 种模板…

C#调用OpenCvSharp和SkiaSharp绘制图像直方图

最近在B站上学习OpenCv教程&#xff0c;学到图像直方图&#xff0c;后者描述的是不同色彩在整幅图像中所占的比例&#xff08;统计不同色彩在图像中的出现次数&#xff09;&#xff0c;可以对灰度图、彩色图等计算并绘制图像直方图。本文学习OpenCvSharp中与计算直方图相关的函…

全志 Android 11:实现响应全局按键

一、篇头 最近实现热键想功能&#xff0c;简单总结了下全志平台Android 11 的响应全局热键的方法。 二、需求 实现全局热键&#xff0c;响应F-、AF、F三个按键&#xff0c;AF只用于启动调焦界面&#xff0c;F-和F除了可以启动调焦界面外&#xff0c;还用于调整镜头的焦距&…

锂电池寿命预测 | Matlab基于ARIMA的锂电池寿命预测

目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 锂电池寿命预测 | Matlab基于ARIMA的锂电池寿命预测 NASA数据集&#xff0c;B0005号电池&#xff0c;选择前110个数据训练&#xff0c;后58个数据测试预测。程序包含去趋势线、差分、平稳化及AIC准则判定p和q。命令窗…

幂集000

题目链接 幂集 题目描述 注意点 集合中不包含重复的元素 解答思路 可以使用深度优先遍历的思想按顺序将相应的元素添加到子集中&#xff0c;并将每个子集添加到结果集 代码 class Solution {public List<List<Integer>> subsets(int[] nums) {List<List&…

openGauss安装流程2024

openGauss安装流程2024 报错解决&#xff1a;https://blog.csdn.net/weixin_47115107/article/details/139844012?spm1001.2014.3001.5501 openGauss安装 之后安装过程中openGauss用户互信&#xff0c;openEuler服务器需要用到Python-3.7.x命令&#xff0c;但是默认Python版…

GNSS边坡监测站

TH-WY1随着科技的飞速发展&#xff0c;各种先进的监测技术不断涌现&#xff0c;为边坡安全监测提供了有力保障。其中&#xff0c;GNSS边坡监测站以其高精度、实时性强的特点&#xff0c;受到了广泛关注。 GNSS边坡监测站&#xff0c;全称为全球导航卫星系统边坡监测站&#xf…

掌握心理学知识成为产品经理一门必修课?

文章目录 心理学与产品设计的关联关系产品经理需要学习哪些心理学知识产品心理学的学习对象包含哪些 谈及心理学&#xff0c;往往认为它是一门研究人类心理现象及其影响下的精神功能和行为活动的科学&#xff0c;很多情况下&#xff0c;我们的直观印象是把心理学与医学领域进行…

代码随想录刷题复习day01

day01 数组-二分查找 class Solution {public int search(int[] nums, int target) {// 左闭右闭int left 0;int right nums.length - 1;int mid 0;while (right > left) {mid left (right - left) / 2;if (nums[mid] > target)right mid - 1;else if (nums[mid]…

HoVer-Net复现:手把手带你实现细胞核的分割与分类,并输出叠加图像|24-06-21

小罗碎碎念 先说一下&#xff0c;只要你跟着我一步一步走&#xff0c;你能实现的效果——对细胞核进行分割和分类&#xff0c;并在原始图像上以颜色叠加的方式直观地展示这些结果。 昨天我在交流群里进行了一下预热&#xff0c;并且提供了一些前期的教程&#xff0c;反响还不…

会声会影2024专业免费版下载附带激活码序列号

&#x1f31f; 会声会影2024&#xff1a;你的视频编辑新伙伴&#xff01;大家好&#xff0c;今天来给你们安利一个超级棒的视频编辑软件——会声会影2024最新版本&#xff01;作为一位热爱创作的小伙伴&#xff0c;找到一款既强大又易用的视频编辑工具真的太重要了。而会声会影…

CentOS 8.5 - 配置ssh的免密登录

文章目录 生成ssh密钥公钥内容放入服务器 生成ssh密钥 在本地主机安装 ssh工具&#xff0c;并生成公钥、私钥。 # 命令行输入 ssh-keygen -r rsa# 会在当前用户的家目录下生成一个.ssh目录公钥内容放入服务器 将上一步生成的id_rsa.pub公钥的内容复制到远程服务器 # 编辑文…

【Golang - 90天从新手到大师】Day11 - 包的管理

系列文章合集 Golang - 90天从新手到大师 Go语言中包的使用 Go语言使用包&#xff08;package&#xff09;这种语法元素来组织源码&#xff0c;所有语法可见性均定义在package这个级别&#xff0c;与Java 、python等语言相比&#xff0c;这算不上什么创新&#xff0c;但与C传…

跨区域文件管控解决方案,一文了解

跨区域文件管控是一个涉及在不同地域或区域之间管理和控制文件的过程&#xff0c;它包括安全性、合规性和管理效率等多个方面。以下是一些关键的考量因素&#xff1a; 1.安全性&#xff1a;确保在传输过程中文件不被截获、篡改或泄露。使用加密技术保护文件&#xff0c;并确保传…

递推和递归

递推 何为递推 用若干步可重复运算来描述复杂问题的方法 递推算法是一种用若干步可重复运算来描述复杂问题的方法。递推是序列计算中的一种常用算法。通常是通过计算前面的一些项来得出序列中的指定项的值。 经典例题 import java.util.Scanner;public class Tuzi {static …