掌握多线程之精髓:优雅地等待线程结果并继续后续操作

news2024/11/22 20:30:34

在当今这个信息爆炸的时代,多线程编程已成为高效处理并发任务的重要工具。然而,如何在多线程编程中优雅地等待线程结果并继续后续操作,却是一个让人头疼的问题。今天,我们就来探讨如何使用Executors.newFixedThreadPool和executorService.submit(callable)来解决这个问题,让你的代码更加高效、易读。

一、为什么要使用多线程等待线程结果?

在Java中,多线程编程可以显著提高程序的执行效率,尤其是在处理大量并发任务时。然而,当多个线程同时执行时,如何确保它们按照预期的顺序执行,即等待某个线程完成后才继续执行后续操作,就显得尤为重要。这不仅可以避免线程间的竞争和冲突,还能保证程序的正确性和稳定性。

二、Executors.newFixedThreadPool的优势

Executors.newFixedThreadPool是Java中提供的一个非常实用的线程池创建方法。它创建了一个固定大小的线程池,可以重复利用已创建的线程执行新任务,避免了频繁创建和销毁线程带来的性能损耗。此外,线程池还可以有效地控制并发线程的数量,防止因过多线程同时执行而导致的系统资源耗尽。

三、executorService.submit(callable)的使用方法

executorService.submit(callable)是线程池ExecutorService中的一个重要方法。它允许你将一个Callable任务提交给线程池执行,并返回一个Future对象,该对象代表了任务的执行结果。通过Future对象,你可以获取任务的执行结果,或者在任务完成时执行回调函数等操作。

    /**
     * 加入线程
     * @param callable
     */
    public void submit(Callable<Object> callable){
        Future<Object> future = executorService.submit(callable);
        futures.add(future);
    }
四、如何优雅地等待线程结果并继续后续操作

在使用executorService.submit(callable)提交任务后,你可以通过调用Future.get()方法来获取任务的执行结果。这个方法会阻塞当前线程,直到任务完成并返回结果。虽然这种方法可以获取到结果,但它并不优雅,因为它会阻塞当前线程,影响程序的并发性能。

为了优雅地等待线程结果并继续后续操作,我们可以通过Future.get()方法获取结果;如果任务还未完成,我们可以选择执行其他操作,或者通过轮询的方式等待任务完成。

    /**
     * 加入线程
     * @param callable
     */
    public void submit(Callable<Object> callable){
        Future<Object> future = executorService.submit(callable);
        futures.add(future);
    }

    /**
     * 等待线程全部执行完毕,并返回结果数据
     */
    public List<Object> waitComplete(){
        try {
            // 等待所有任务完成并打印结果
            for (Future<Object> future : futures) {
                result.add(future.get());// future.get()会阻塞,直到结果可用
            }
            return this.result;
        }catch (Exception exception){
            throw new GlobalException("获取线程结果失败:" + exception.getMessage());
        }finally {
            executorService.shutdown();
        }
    }

此外,我们还可以通过CompletableFuture类来实现更加灵活的异步编程。CompletableFuture提供了丰富的API,支持任务的链式调用、异常处理、结果转换等操作,使得多线程编程变得更加简单和高效。

五、总结

通过Executors.newFixedThreadPool和executorService.submit(callable)的结合使用,我们可以轻松地实现多线程编程,并通过优雅地等待线程结果来继续后续操作。这不仅提高了程序的执行效率,还增强了程序的可读性和可维护性。在未来的开发中,我们应该充分利用这些多线程编程技巧,编写出更加高效、稳定的代码。

完整代码
public class FixedThreadPoolUtil {

    int nThreads;
    ExecutorService executorService = null;
    List<Future<Object>> futures = new ArrayList<>();
    List<Object> result = new ArrayList<>();

    /**
     * 新建线程池,指定线程池大小
     * @param nThreads
     */
    public FixedThreadPoolUtil(int nThreads){
        this.nThreads = nThreads;
        executorService = Executors.newFixedThreadPool(nThreads);
    }

    /**
     * 加入线程
     * @param callable
     */
    public void submit(Callable<Object> callable){
        Future<Object> future = executorService.submit(callable);
        futures.add(future);
    }

    /**
     * 等待线程全部执行完毕,并返回结果数据
     */
    public List<Object> waitComplete(){
        try {
            // 等待所有任务完成并打印结果
            for (Future<Object> future : futures) {
                result.add(future.get());// future.get()会阻塞,直到结果可用
            }
            return this.result;
        }catch (Exception exception){
            throw new GlobalException("获取线程结果失败:" + exception.getMessage());
        }finally {
            executorService.shutdown();
        }
    }

    /**
     * 关闭线程池
     */
    protected void finalize() {
        if (executorService != null) {
            executorService.shutdown();
        }
    }

    /**
     * 调用demo
     */
    private void demo(){
        FixedThreadPoolUtil fixedThreadPoolUtil = new FixedThreadPoolUtil(2);
        Callable<Object> callable1 = new Callable<Object>() {
            private int tenxunService;
            private String imgUrl;
            public Callable<Object> withParameter(int tenxunService,String imgUrl) {
                this.tenxunService = tenxunService;
                this.imgUrl = imgUrl;
                return this;
            }
            @Override
            public Object call(){
                return this.imgUrl;
            }
        }.withParameter(1,"1");
        fixedThreadPoolUtil.submit(callable1);
        List<Object> objects = fixedThreadPoolUtil.waitComplete();
        System.out.println(objects);
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

让IIS支持.NET Web Api PUT和DELETE请求

前言 有很长一段时间没有使用过IIS来托管应用了&#xff0c;今天用IIS来托管一个比较老的.NET Fx4.6的项目。发布到线上后居然一直调用不同本地却一直是正常的&#xff0c;关键是POST和GET请求都是正常的&#xff0c;只有PUT和DELETE请求是有问题的。经过一番思考忽然想起来了I…

如何在群晖NAS中创建FTP公网地址实现远程上传下载本地文件

文章目录 1. 群晖安装Cpolar2. 创建FTP公网地址3. 开启群晖FTP服务4. 群晖FTP远程连接5. 固定FTP公网地址6. 固定FTP地址连接 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 人工智能学习网站&#xff0c; 通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分…

基于STELLA系统动态模拟技术及在农业、生态及环境科学中的应用教程

原文链接&#xff1a;基于STELLA系统动态模拟技术及在农业、生态及环境科学中的应用教程http://基于STELLA系统动态模拟技术及在农业、生态及环境科学中的应用教程 前言 STELLA是一种用户友好的计算机软件。通过绘画出一个系统的形象图形&#xff0c;并给这个系统提供数学公式…

WEBSERVICE 大文件上传,断点续传分段

最新版本&#xff1a;6.5.40 在线代码&#xff1a;up6-asp-net: Web大文件上传-asp.net示例 - Gitee.com 视频教程&#xff1a;https://www.ixigua.com/7200367234802418187 NOSQL NOSQL无需任何配置可直接访问页面进行测试 SQL 使用IIS 大文件上传测试推荐使用IIS以获取更…

伦敦金实时行情交易需要了解的3个事实

在伦敦金市场中&#xff0c;我们要交易就要面对伦敦金实时行情。然而&#xff0c;在伦敦金实时行情交易中&#xff0c;有几个事实是我们不得不去了解的&#xff0c;下面我们就来讨论一下。 盈利的经历不等于盈利的能力。我们经常看到一些卖课的或者卖指标、卖策略的人会宣传自己…

大数据篇 一篇讲明白 Hadoop 生态的三大部件

大数据Hadoop 生态的三大部件的目录 往期热门专栏回顾前言1、HDFS2、Yarn3、Hive4、HBase4.1&#xff0e;特点4.2&#xff0e;存储 5、Spark及Spark Streaming关于作者 往期热门专栏回顾 专栏描述Java项目实战介绍Java组件安装、使用&#xff1b;手写框架等Aws服务器实战Aws L…

linux系统systemd使用

一、开机启动 所有支持systemd的服务&#xff0c;在安装后&#xff0c;会在/usr/lib/systemd/system中添加一个配置文件&#xff0c;如果需要让当前的服务在开机的时候自动启动&#xff0c;则需要执行以下命令&#xff0c;以firewalld为例 systemctl enable firewalld.servic…

全局UI方法-弹窗六-自定义弹窗

1、描述 通过CustomDialogController类显示自定义弹窗。使用弹窗组件时&#xff0c;可优先考虑自定义弹窗&#xff0c;便于自定义弹窗的样式与内容。 2、接口 CustomDialogController(value:{builder: CustomDialog, cancel?: () > void, autoCancel?: boolean, alignme…

精品凉拌菜系列热卤系列课程

这一系列课程涵盖精美凉拌菜和美味热卤菜的制作技巧。学员将学习如何选材、调味和烹饪&#xff0c;打造口感丰富、色香俱佳的菜肴。通过实践训练&#xff0c;掌握独特的烹饪技能&#xff0c;为家庭聚餐或职业厨艺提升增添亮点。 课程大小&#xff1a;6.6G 课程下载&#xff1…

Linux系统使用Docker搭建Traefik结合内网穿透实现公网访问管理界面

文章目录 一、Zotero安装教程二、群晖NAS WebDAV设置三、Zotero设置四、使用公网地址同步Zotero文献库五、使用永久固定公网地址同步Zotero文献库 Zotero 是一款全能型 文献管理器,可以 存储、管理和引用文献&#xff0c;不但免费&#xff0c;功能还很强大实用。 ​ Zotero 支…

修改mysql密码

1.在此处文件夹下打开cmd 2.输入命令mysqladmin -uroot -p旧密码 password 新密码 3.在navicat进行测试连接

鱼哥赠书活动第14期:看完这本《数字化运维》掌握数字化运维方法,构建数字化运维体系

鱼哥赠书活动第14期&#xff1a;看完这本《数字化运维》掌握数字化运维方法&#xff0c;构建数字化运维体系 主要内容&#xff1a;读者对象&#xff1a;赠书抽奖规则:往期赠书福利&#xff1a; 数字化转型已经成为大势所趋&#xff0c;各行各业正朝着数字化方向转型&#xff0c…

请查收!一份Go代码优化实用指南

Go非常适合构建高性能应用&#xff0c;本文通过对整型切片求和代码的优化&#xff0c;介绍了常用的Go代码优化方案&#xff0c;从而让代码获得更好的性能。原文: Optimizing Go Code: A Practical Guide 代码优化是软件开发流程中的关键步骤&#xff0c;从而确保程序高效运行、…

Vercel搭建线上项目 (无服务器版-免费)

前言 假如想做一个简单的功能&#xff0c;例如一个博客网站或网页小程序&#xff0c;以往我是要先花几百元购买ECS服务器&#xff0c;在服务器上安装运维面板、再安装Nginx、MySQL、NodeJS、Java、PHP等环境&#xff0c;最后实现一个API服务器。 这种传统模式不但有着较高的技…

企业指标体系的落地与推广:让指标体系真正发挥作用

一、精心策划实施计划&#xff0c;确保项目有序进行 为确保指标体系的顺利落地与推广&#xff0c;我们精心策划了实施计划。首先&#xff0c;我们制定了详细的时间表&#xff0c;明确了项目启动、关键节点和结束时间&#xff0c;确保项目能够按期推进。同时&#xff0c;我们还将…

rtph264depay插件分析笔记

1、rtp协议头 2、rtp可以基于TCP或者UDP 其中基于TCP需要加4个字节的RTP标志 3、rtph264depay定义解析函数gst_rtp_h264_depay_process&#xff0c;通过RFC 3984文档实现。 static void gst_rtp_h264_depay_class_init (GstRtpH264DepayClass * klass) {GObjectClass *gobject…

C++初阶:2_类与对象(下)

类与对象(下) 一.再谈构造函数 1. 构造函数体赋值 在创建对象时&#xff0c;编译器通过调用构造函数&#xff0c;给对象中各个成员变量一个合适的初始值。 class Date { public:Date(int year, int month, int day){_year year;_month month;_day day;} private:int _ye…

Kubernetes容器平台下的 GPU 集群算力管控

引言 随着最近一两年生成式大模型的迭代出新&#xff0c;尤其是以 ChartGPT 为代表的大语言模型&#xff0c;几乎一夜间让所有人都看到了人工智能改变世界的潜力。而作为持续发力 GPU 通用计算&#xff08;CUDA&#xff09;的 AI 专业显卡提供商&#xff0c;Nvidia 公司成为了…

人大金仓数据库介绍与使用指南

人大金仓数据库是一款强大的关系型数据库管理系统&#xff0c;具有简单易用、高性能和稳定可靠的特点。本文将介绍人大金仓数据库的安装方法、常用的SQL语法以及相关工具的使用。 一、安装方法&#xff1a; 1、下载人大金仓数据库安装程序&#xff1b; 2、运行安装程序&#…

事件穿透效果

讲述一下事件穿透的需求&#xff0c;大家可以根据实际情况来考虑是否采用这种方式来制作页面&#xff0c;&#xff08;项目中遇到了底部是地图&#xff0c;两侧面板&#xff0c;但是UI在设计的时候为了好看&#xff0c;会有很大的遮罩阴影部分&#xff0c;如果按照时间制作会导…