面试官:如何让主线程等待所有的子线程执行结束之后再执行?我懵了

2023-05-16

使用Thread的join方法

package com.qcy.testThreadFinish;

/**
 * @author qcy
 * @create 2020/09/09 17:05:23
 */
public class Case1 {
    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t1.start();

        Thread t2 = new Thread(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t2.start();

        t1.join();
        t2.join();
        System.out.println("主线程结束");
    }
}

join()方法使得主线程等待子线程执行结束,阻塞的是主线程。其底层原理,可以参考我的这篇文章你真得懂Thread.join吗?


使用线程池的isTerminated方法

package com.qcy.testThreadFinish;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author qcy
 * @create 2020/09/09 17:05:23
 */
public class Case2 {
    public static void main(String[] args) {

        ExecutorService pool = Executors.newFixedThreadPool(3);

        pool.execute(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        pool.execute(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        //不再接受新的任务
        pool.shutdown();
        
        while (true) {
            //手动循环确实效率很低,不推荐
            if (pool.isTerminated()) {
                System.out.println("线程池中的任务执行结束");
                break;
            }
        }
        System.out.println("主线程结束");
    }
}

isTerminated,当调用shutdown()方法后,并且所有提交的任务完成后才会返回为true

这里直接使用了固定大小的线程池,线程池的参数在面试中也经常被问到,对线程池不熟悉的同学,可以参考我的这篇文章说说线程池


使用Future机制

package com.qcy.testThreadFinish;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author qcy
 * @create 2020/09/09 17:05:23
 */
public class Case4 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        ExecutorService pool = Executors.newFixedThreadPool(3);

        Future<Integer> task1 = pool.submit(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 2;
        });

        Future<Integer> task2 = pool.submit(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 3;
        });

        //不再接受新的任务
        pool.shutdown();
        
        //get方法为阻塞获取
        System.out.println("task1的运行结果:" + task1.get());
        System.out.println("task2的运行结果:" + task2.get());

        System.out.println("主线程结束");
    }
}

Future机制,可以参考我的另外一篇博客谈谈Runnable、Future、Callable、FutureTask之间的关系


使用CountDownLatch

package com.qcy.testThreadFinish;

import java.util.concurrent.CountDownLatch;

/**
 * @author qcy
 * @create 2020/09/09 17:05:23
 */
public class Case5 {
    public static void main(String[] args) throws InterruptedException {

        CountDownLatch latch = new CountDownLatch(2);

        Thread t1 = new Thread(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                latch.countDown();
            }
        });
        t1.start();

        Thread t2 = new Thread(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                latch.countDown();
            }
        });
        t2.start();

        latch.await();
        System.out.println("主线程结束");
    }
}

每调用一次countDown方法,计数器会减1,在计数器减为0之前,await方法将会阻塞主线程。有关CountDownLatch的底层原理,可以参考我的另外一篇博客CountDownLatch实现原理


使用CompletableFuture

package com.qcy.testThreadFinish;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * @author qcy
 * @create 2020/09/09 17:05:23
 */
public class Case6 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {

        CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 2;
        });

        CompletableFuture<Integer> cf = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 3;
        }).thenCombine(cf1, (result1, result2) -> result1 * result2);

        //get方法为阻塞获取
        System.out.println("计算结果为" + cf.get());
        System.out.println("主线程结束");
    }
}

等到两个子任务都完成后,输出两数之积,再执行主线程。对CompletableFuture不熟悉的同学,可以参考我的这一篇文章什么,你还不会用CompletableFuture?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

面试官:如何让主线程等待所有的子线程执行结束之后再执行?我懵了 的相关文章

随机推荐

  • mysql数据库自动备份

    前言 服务器中数据库的数据是最重要的东西 如果因为某些情况导致数据库数据错误 数据错乱或数据库崩溃 这时一定要及时的修复 但如果数据丢失或数据没法用了 这时就要回滚数据了 而这时就需要我们经常的备份数据库的数据 正文 一般别人都会推荐使用N
  • 坑爹的微信支付(签名错误)

    前言 以前调微信支付 直接把demo粘过来改改 或者从老项目粘过来 这次接手一个一年之前的项目 说微信支付没调通 好吧 我就调吧 正文 1 之前的body写的是中文 改成英文 结果 失败 不过这一步很必要 2 传递的xml编码换为UTF 8
  • androidx使用FileProvider适配安卓7

    前言 安卓7版本后 需要适配获取本地uri 否则会报错 之前用的android support库 可以参考这篇文章 lt 点击查看 gt 但是现在使用了androidx后 发现清单文件中配置不一样了 适配方法 以前是 lt provider
  • Kotlin优雅的使用sp(SharedPreferences)

    前言 我平时用java写的sp工具类 现在有两个需求 第一个是要管理sp的文件名 虽然java可以通过Config的方式配置几个final静态的字符串常量来管理 但是总感觉不够优雅 而且可能存在随便写个文件名 不放在Config内的情况 第
  • binascii.Error: Incorrect padding 报错解决

    输入的base64编码字符串必须符合base64的padding规则 当原数据长度不是3的整数倍时 如果最后剩下两个输入数据 xff0c 在编码结果后加1个 61 xff1b 如果最后剩下一个输入数据 xff0c 编码结果后加2个 61 x
  • Java类成分和四大属性

    Java类定义和四大属性 Java类成分面向对象思想概述类的五大成分类的构造器封装this关键字static关键字成员变量的分类和访问 继承 extends Java类成分 面向对象思想概述 Java是一种面向对象的高级编程语言 面向对象
  • python绘制激活函数曲线图及其导数曲线图,激活函数包括sigmoid、relu、tanh

    因写大论文需要 xff0c 在知网上别人的论文中扣下来清晰度不够 xff0c 其他网页上截屏下来可能包含水印 xff0c 同时也比较难找全 因此参考CSDN博客资料 xff0c 自己画出来用于论文书写 span class token ke
  • cv2.error: color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function ‘cv::cvtColor‘

    该文章主要解决使用coco格式数据报错 xff01 将标注完成的数据集通过xml2coco xff08 转换代码 xff09 后生成coco数据集格式 运行train py xff0c 出现标题的报错 xff0c 出现该错误的原因和解决办法
  • 在安装之后使用labelme出现qtpy.PythonQtError:No Qt bindings could be found错误

    我在base环境 xff08 python3 7 可成功安装和使用labelme xff0c 而在同py37版本和py36的虚拟环境中可安装labelme包 xff0c 但在使用的时候出现报错 xff0c 如下 xff1a 我尝试着去解决第
  • 解决RuntimeError: implement_array_function method already has a docstring报错问题

    该问题的报错最后一行显示为 xff1a RuntimeError implement array function method already has a docstring 在其错误上面所提示的信息可得知 xff0c pandas nu
  • 最小二乘圆拟合模型公式推导&MATLAB代码求圆拟合

    理论部分1 xff1a https wenku baidu com view ecda32525beef8c75fbfc77da26925c52dc59156 html 最小二乘圆拟合模型公式推导 理论部分2 xff1a https blo
  • 在windows11安装VMware & ubuntu

    在win11安装虚拟机 xff08 win11 43 VMware16 43 ubuntu18 04 xff09 xff0c 遇到的一些情况进行记录 xff1a 1 安装VMware 下载 VMware Workstation Pro 2
  • MATLAB diag & spdiags函数的使用

    diag amp spdiags函数的使用 xff1a 下面对diag 函数和spdiags函数进行了实例演示 xff0c 特别注意的是spdiags函数 xff1a 1 Bout d 61 spdiags A 矩阵A mn xff0c 当
  • diskpart命令创建GPT磁盘分区

    利用diskpart命令创建GPT磁盘分区图文教程很多朋友都是使用工具软件完成创建GPT磁盘分区 xff0c 实际上你无论你是使用光盘 U盘还是硬盘 NT6 等方式全新安装Win7或者Win8系统 xff0c 都可以利用diskpart命令
  • slf4j使用xml配置日志不能显示的问题

    在我使用slf4j的xml配置方式的时候 一直加载不出xml的配置文件 导致里面的设置不能被读取 控制台一直打印不去日志信息 正在寻找解决办法 报的错误是 log4j WARN Please initialize the log4j sys
  • Steghide使用教程及其密码爆破

    Steghide使用教程及其密码爆破 工具介绍 Steghide是一款开源的隐写术软件 xff0c 它可以让你在一张图片或者音频文件中隐藏你的秘密信息 xff0c 而且你不会注意到图片或音频文件发生了任何的改变 而且 xff0c 你的秘密文
  • Navicat如何连接远程服务器的MySQL

    前言 xff1a 运行环境及工具 Navicat for Mysql 腾讯云轻量级服务器一台 xff08 Centos 7 xff09 Mysql 8 0 24 xff08 远程服务器内安装的 xff09 Xshell7 xff08 连接操
  • 警告!你的隐私正在被上亿网友围观偷看!

    你的隐私正在被上亿万网友围观偷看 xff01 事情要从一款被推荐到烂的软件说起 Everything 这个软件想必很多同学都有听过 xff0c 是一款非常好用的文件搜索软件 xff0c 很多同学把它设置为开机必启动项之一 简单来说 Ever
  • Ubuntu安装JDK教程

    Ubuntu安装JDK教程 jdk的下载和安装 xff1a 1 打开浏览器 xff0c 输入jdk的官网地址 xff1a https www oracle com java technologies javase downloads htm
  • 面试官:如何让主线程等待所有的子线程执行结束之后再执行?我懵了

    使用Thread的join方法 package com qcy testThreadFinish 64 author qcy 64 create 2020 09 09 17 05 23 public class Case1 public s