并发编程 | Future是如何优化程序性能
在初识Future一文中介绍了Future的核心方法。本文中接着介绍如何用Future优化我们的程序性能。 在此之前,有必要介绍Future接口的一个实现类FutureTask。
FutureTask介绍
FutureTask继承结构
首先我们看一下FutureTask的继承结构:
public class FutureTask<V> implements RunnableFuture<V>{...
}public interface RunnableFuture<V> extends Runnable, Future<V> {void run();
}
可以看出,FutureTask实现了RunnableFuture接口,而RunnableFuture继承了Runnable和Future,也就是说FutureTask既是Runnable,也是Future。所以 FutureTask 既可以作为 Runnable 被线程执行,又可以作为 Future 得到 Callable 的返回值。
下面的例子展示了FutureTask的 简单 用法 :
class FutureTaskCallable implements Callable{@Overridepublic String call() throws Exception {return "Hello FutureTask";}
}public class FutureTaskExample1 {public static void main(String[] args) throws ExecutionException, InterruptedException {FutureTask<String> futureTask =new FutureTask<>(new FutureTaskCallable());Thread thread = new Thread(futureTask);thread.start();System.out.println("子线程返回值:" + futureTask.get());}
}//输出
子线程返回值:Hello FutureTask
这段程序中,可以看出FutureTask类的构造函数是Callable类型;在创建了FutureTask对象后,然后将这个对象当作一个 Runnable 放到 new Thread() 中去执行,最后再用 FutureTask 的 get 得到子线程 的 返回结果。简单介绍完FutureTask,现在可以进入文章的主题了:如何利用Future优化我们的程序性能。
利用Future优化程序
考虑这样一个场景,小码哥突然心血来潮想练练字了,但是他现在手头连一只钢笔都没有,书桌也是乱糟糟的,于是他打算在网购一支钢笔,然后整理书桌,就开始练字,用代码实现这个场景
普通多线程版本
我们先来看普通的多线程版本是如何实现。
//购买钢笔任务
class BuyPenRunnable implements Runnable{private String pen;@Overridepublic void run() {System.out.println("【购买钢笔】:下单,等待送货上门");//模拟送货时间try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("【购买钢笔】:快递送到");pen = "神笔";}public String getPen() {return pen;}
}public class CommomThreadExample {public static void main(String[] args) throws InterruptedException {long startTime = System.currentTimeMillis();BuyPenRunnable buyPenRunnable = new BuyPenRunnable();Thread buyPenThread = new Thread(buyPenRunnable);buyPenThread.start();//模拟整理书桌耗时3000msSystem.out.println("【整理书桌】:开始整理");Thread.sleep(3000);System.out.println("【整理书桌】:整理完了");//保证笔送到buyPenThread.join();//所有准备好,开始练字write(buyPenRunnable.getPen());long endTime = System.currentTimeMillis();System.out.println("总共用时 " + (endTime - startTime) + " ms");}private static void write(String pen){System.out.println("【开始写字】:" + pen);}
}//输出
【购买钢笔】:下单,等待送货上门
【购买钢笔】:快递送到
【整理书桌】:开始整理
【整理书桌】:整理完了
【开始写字】:神笔
总共用时 5020 ms
这里尽管将购买钢笔和整理桌子并行化了,节省了时间,但是这个版本有2个问题:
-
通过 Runnable 实现任务,但为了获取结果,我们需要定义共享变量 pen,并提供一个方法 getPen() 来获取这个变量。
-
任务的取消和状态检查不方便。
Future实现
利用FutureTask实现上面的功能,代码如下:
//购买钢笔任务
class BuyPenCallable implements Callable {@Overridepublic String call() {System.out.println("【购买钢笔】:下单,等待送货上门");//模拟送货时间try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("【购买钢笔】:快递送到");return "神笔";}
}public class FutureTaskExample {public static void main(String[] args) throws InterruptedException, ExecutionException {long startTime = System.currentTimeMillis();Callable<String> buyPenCallable = () -> {System.out.println("【购买钢笔】:下单,等待送货上门");// 模拟送货时间try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("【购买钢笔】:快递送到");return "神笔";};FutureTask<String> futureTask = new FutureTask<>(buyPenCallable);ExecutorService executor = Executors.newFixedThreadPool(1);executor.submit(futureTask);// 模拟整理书桌耗时3000msSystem.out.println("【整理书桌】:开始整理");Thread.sleep(3000);System.out.println("【整理书桌】:整理完了");// 尝试取消任务,如果需要这么做//boolean cancelled = future.cancel(false); // 等待获取笔的结果String pen = futureTask.get();// 所有准备好,开始练字write(pen);long endTime = System.currentTimeMillis();System.out.println("总共用时 " + (endTime - startTime) + " ms");executor.shutdown();}private static void write(String pen) {System.out.println("【开始写字】:" + pen);}
}
上面的代码中,可以看到,FutureTask实现的实现方式:
-
获取结果更方便:通过 Callable 的 call() 方法直接返回结果,不需要显式地定义共享变量和同步机制。
-
对线程的管理更方便:FutureTask 提供了 cancel() 方法,可以取消任务,并通过 isCancelled() 和 isDone() 方法检查任务状态。
总结
在我们的实际项目中,很多时候我们的接口需要通过rpc调用去调用其它的多个服务拿到结果聚合,如果采用同步调用的方式,假设一次远程调用的时间为 300ms,则一个 Client 同步对三个 Server 分别进行一次 RPC 调 用的总时间,需要耗费 900ms。
如果使用 Future 模式对其进行改造,将同步的 RPC 调用改为异步并发的 RPC 调用,一个 Client 异步并发对三个 Server 分别进行一次 RPC 调用,那么正常情况下,大约只需要 300ms就能拿到所有服务的数据了。Future的好处不言而喻。
相关文章:

并发编程 | Future是如何优化程序性能
在初识Future一文中介绍了Future的核心方法。本文中接着介绍如何用Future优化我们的程序性能。 在此之前,有必要介绍Future接口的一个实现类FutureTask。 FutureTask介绍 FutureTask继承结构 首先我们看一下FutureTask的继承结构: public class Futur…...
Oracle笔记
一、 如何解决 sqlplus 无法使用退格键和方向键 .bashrc 中添加如下内容,解决 退格键 stty erase ^h 安装 rlwap 后,执行如下命令可解决 方向键 rlwap sqlplus 二、 都有哪些备份数据到工具 三、 谈谈 你对 oracle 中实例和数据库的理解 数据库是一…...

LVS+Keepalived 双机热备
LVSKeepalived 双机热备 Keepalived案例分析Keepalived工具介绍Keepalived工具介绍一、功能特点 一、理解Keepalived实现原理实验报告资源列表一、安装keepalived以及ipvsadm Keepalived案例分析 企业应用中,单台服务器承担应用存在单点故障的危险单点故障一旦发生…...

Web Image scr图片从后端API获取基本实现
因系统开发中需求,会有页面显示图片直接从后端获取后显示,代码如下: 后端: /*** 获取图片流* param response* param fileName*/RequestMapping(value"getImgStream",method RequestMethod.GET)public void getImgStr…...

2024音频剪辑指南:探索四大高效工具!
音频剪辑不仅仅是技术活,更是一种艺术创作,它能够让声音更加生动、更具感染力。今天,我们就来探索几款优秀的音频剪辑工具。 福昕音频剪辑 链接:www.pdf365.cn/foxit-clip/ 福昕音频剪辑是一款界面简洁、操作直观的音频编辑软件…...

“CSS”第一步——WEB开发系列13
CSS (Cascading Style Sheets,层叠样式表),是一种用来为结构化文档(如 HTML 文档或 XML 应用)添加样式(字体、间距和颜色等)的计算机语言,CSS 文件扩展名为 .css。 一、什么是 CSS&a…...

IEEE802网络协议和标准
IEEE802网络协议和标准 802委员会IEEE 802介绍现有标准 IEEE 802.3介绍物理媒介类型MAC子层与LLC子层主要内容通讯标准POE供电标准802.3af、802.3at、802.3btIEEE802.3af的工作过程:IEEE802.3af主要供电参数:IEEE802.3af的分级参数:为什么会有…...

vulnhub靶机 DC-9(渗透测试详解)
一、靶机信息收集 1、靶机下载 https://download.vulnhub.com/dc/DC-9.zip 2、靶机IP扫描 3、探测靶机主机、端口、服务版本信息 4、靶机目录扫描 二、web渗透测试 1、访问靶机IP 查看页面功能点,发现一个搜索框和登录框 2、测试一下是否存在sql注入 查看当前数…...

javaweb的新能源充电系统pf
TOC springboot339javaweb的新能源充电系统pf 第1章 绪论 1.1 课题背景 二十一世纪互联网的出现,改变了几千年以来人们的生活,不仅仅是生活物资的丰富,还有精神层次的丰富。在互联网诞生之前,地域位置往往是人们思想上不可跨域…...

如何在桌面同时展示多个窗口
一、实现2分屏显示 win箭头 二、实现3分屏显示 1. 在实现2分屏显示的基础上,再次点击箭头图标,这次选择屏幕的上方或下方。 2. 点击后,第三个窗口将会出现在你选择的区域。现在,你可以在三个窗口之间自由切换,提高工…...

The Sandbox 游戏制作教程(第 5 部分):创建基于分类的系统
欢迎回到我们的系列,我们将记录 The Sandbox Game Maker 的 “On-Equip”(装备)功能的多种用途。 如果你刚加入 The Sandbox,装备功能是 “可收集组件”(Collectable Component)中的一个多功能工具&#x…...
HTML浏览器缓存(Browser Cache)
介绍: 浏览器缓存是Web缓存中最直接、最常见的一种形式。当浏览器首次请求某个资源时,如果服务器响应中包含了缓存控制指令(如Cache-Control、Expires等),浏览器就会将这些资源存储在本地缓存中。后续请求相同资源时&a…...

短剧APP系统,推动短剧市场发展
近年来,短剧作为一直火爆的新兴行业,凭借着剧情进奏、爽、时长短等优势,深受大众欢迎,成为了大众碎片化时间的解压神器。 目前,随着短剧市场的快速发展,各个类型的短剧层出不穷,也推动了短剧AP…...

嵌入式 | 嵌入式 Linux 系统使用摄像头
点击上方"蓝字"关注我们 01、引言 >>> 在嵌入式 Linux 系统使用摄像头 俗话说“眼见为实”,这或许是为什么近年来摄像头在嵌入式系统上快速增长的原因。它们被用于不同的场景,如: 远程监控:典型的例子是闭路电视,监控人员在监视环境(或许你所在的大楼…...

C 开源库之cJSON
cJSON简介 CJSON库是一个用于解析和生成JSON数据的C语言库。 它提供了一组函数,使得在C语言中操作JSON数据变得简单而高效。 您可以使用CJSON库来解析从服务器返回的JSON数据,或者将C语言数据结构转换为JSON格式以进行传输。 cJSON 使用 官网地址&…...

ROW_NUMBER(), RANK(), DENSE_RANK() SQL排序函数图文详解
ROW_NUMBER(), RANK(), DENSE_RANK() ROW_NUMBER(): 为结果集中的每一行分配唯一的连续编号。即使有重复的值,ROW_NUMBER() 也会为它们分配不同的序号。 SELECT column_name, ROW_NUMBER() OVER (ORDER BY column_name) AS row_num FROM table_name;2. RANK(): 对结…...

Spring IoCDI(下)—DI的尾声
我们之前学习了控制反转IoC,接下来就开始学习依赖注入DI的细节。 依赖注入是一个过程,是指IoC容器在创建Bean时,去提供运行时所依赖的资源,而资源指的就是对象。我们使用 Autowired 注解,完成依赖注入的操作。简单来说…...

仕考网:考外省公务员可以调回本地吗?
一般情况下,公务员岗位是固定不可随意更换的,因为每个职位都对应特定的职责和要求。一旦考到外地的岗位,想要调回本地几乎是不可能的。因为这样的操作可能导致职位空缺,进而需要通过公共招聘流程来填补,而不是简单地从…...
《工厂模式在软件开发中的深度剖析与应用》
工厂模式 在软件开发的领域中,设计模式充当着解决常见问题的高效且可复用的策略角色。其中,工厂模式作为创建对象的重要设计模式,具有不可小觑的应用价值。接下来,我们将深入探讨简单工厂模式、工厂方法模式和抽象工厂模式。 一…...
双向通信之Websocket
介绍 Websocket是一种在单个TCP连接上进行全双工通信的协议。与传统的HTTP协议不同,websocket允许客户端与服务器之间的双向通信,可以在同一条连接上进行多次消息的快速传递。我之前在做一个线上刷题网站的时候,需要设计一个社区讨论模块&am…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...

【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...

基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...