当前位置: 首页 > news >正文

并发编程 | 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个问题:

  1. 通过 Runnable 实现任务,但为了获取结果,我们需要定义共享变量 pen,并提供一个方法 getPen() 来获取这个变量。

  2. 任务的取消和状态检查不方便。

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优化我们的程序性能。 在此之前&#xff0c;有必要介绍Future接口的一个实现类FutureTask。 FutureTask介绍 FutureTask继承结构 首先我们看一下FutureTask的继承结构&#xff1a; public class Futur…...

Oracle笔记

一、 如何解决 sqlplus 无法使用退格键和方向键 .bashrc 中添加如下内容&#xff0c;解决 退格键 stty erase ^h 安装 rlwap 后&#xff0c;执行如下命令可解决 方向键 rlwap sqlplus 二、 都有哪些备份数据到工具 三、 谈谈 你对 oracle 中实例和数据库的理解 数据库是一…...

LVS+Keepalived 双机热备

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

Web Image scr图片从后端API获取基本实现

因系统开发中需求&#xff0c;会有页面显示图片直接从后端获取后显示&#xff0c;代码如下&#xff1a; 后端&#xff1a; /*** 获取图片流* param response* param fileName*/RequestMapping(value"getImgStream",method RequestMethod.GET)public void getImgStr…...

2024音频剪辑指南:探索四大高效工具!

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

“CSS”第一步——WEB开发系列13

CSS (Cascading Style Sheets&#xff0c;层叠样式表&#xff09;&#xff0c;是一种用来为结构化文档&#xff08;如 HTML 文档或 XML 应用&#xff09;添加样式&#xff08;字体、间距和颜色等&#xff09;的计算机语言&#xff0c;CSS 文件扩展名为 .css。 一、什么是 CSS&a…...

IEEE802网络协议和标准

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

vulnhub靶机 DC-9(渗透测试详解)

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

javaweb的新能源充电系统pf

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

如何在桌面同时展示多个窗口

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

The Sandbox 游戏制作教程(第 5 部分):创建基于分类的系统

欢迎回到我们的系列&#xff0c;我们将记录 The Sandbox Game Maker 的 “On-Equip”&#xff08;装备&#xff09;功能的多种用途。 如果你刚加入 The Sandbox&#xff0c;装备功能是 “可收集组件”&#xff08;Collectable Component&#xff09;中的一个多功能工具&#x…...

HTML浏览器缓存(Browser Cache)

介绍&#xff1a; 浏览器缓存是Web缓存中最直接、最常见的一种形式。当浏览器首次请求某个资源时&#xff0c;如果服务器响应中包含了缓存控制指令&#xff08;如Cache-Control、Expires等&#xff09;&#xff0c;浏览器就会将这些资源存储在本地缓存中。后续请求相同资源时&a…...

短剧APP系统,推动短剧市场发展

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

嵌入式 | 嵌入式 Linux 系统使用摄像头

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

C 开源库之cJSON

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

ROW_NUMBER(), RANK(), DENSE_RANK() SQL排序函数图文详解

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

Spring IoCDI(下)—DI的尾声

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

仕考网:考外省公务员可以调回本地吗?

一般情况下&#xff0c;公务员岗位是固定不可随意更换的&#xff0c;因为每个职位都对应特定的职责和要求。一旦考到外地的岗位&#xff0c;想要调回本地几乎是不可能的。因为这样的操作可能导致职位空缺&#xff0c;进而需要通过公共招聘流程来填补&#xff0c;而不是简单地从…...

《工厂模式在软件开发中的深度剖析与应用》

工厂模式 在软件开发的领域中&#xff0c;设计模式充当着解决常见问题的高效且可复用的策略角色。其中&#xff0c;工厂模式作为创建对象的重要设计模式&#xff0c;具有不可小觑的应用价值。接下来&#xff0c;我们将深入探讨简单工厂模式、工厂方法模式和抽象工厂模式。 一…...

双向通信之Websocket

介绍 Websocket是一种在单个TCP连接上进行全双工通信的协议。与传统的HTTP协议不同&#xff0c;websocket允许客户端与服务器之间的双向通信&#xff0c;可以在同一条连接上进行多次消息的快速传递。我之前在做一个线上刷题网站的时候&#xff0c;需要设计一个社区讨论模块&am…...

自动化智能体生成+外接MCP,我用 ModelEngine Nexent 5分钟手搓了一个小红书爆款收割机

前言&#xff1a;别让“工作流”困住了你的想象力 在 AI Agent 爆发的这一年&#xff0c;作为开发者&#xff0c;我们采用过“工作流&#xff08;Workflow&#xff09;”开发&#xff0c;提示词开发。 最近体验了 ModelEngine Nexent&#xff0c;它打出的 Slogan 是 “Your n…...

PCB开窗技术:提升电流承载能力的关键工艺

1. PCB开窗技术解析&#xff1a;从概念到应用在PCB设计领域&#xff0c;"开窗"这个术语经常被经验丰富的工程师挂在嘴边&#xff0c;但对于刚入行的新手来说&#xff0c;这个看似简单的操作背后却蕴含着不少设计门道。作为一名有十年硬件设计经验的工程师&#xff0c…...

用随机森林预测空气质量?先看看这6个特征谁说了算!(Python特征重要性分析与可视化实战)

随机森林特征重要性分析&#xff1a;解码空气质量预测的6大关键因素 当数据科学家们谈论空气质量预测时&#xff0c;常常陷入一个误区——过分关注模型的预测准确率&#xff0c;却忽视了模型背后的故事。想象一下&#xff0c;你花费数周时间调优的随机森林模型预测准确率达到了…...

新手必看:Sambert多情感语音合成镜像部署与使用全攻略

新手必看&#xff1a;Sambert多情感语音合成镜像部署与使用全攻略 1. 引言&#xff1a;为什么选择这个语音合成镜像 语音合成技术正在改变我们与数字世界的互动方式。想象一下&#xff0c;你的智能助手不仅能说话&#xff0c;还能根据场景切换不同的情感和音色——这正是Samb…...

【05-log-+-diff:看懂你改了什么、历史是什么】

第五篇&#xff1a;log diff&#xff1a;看懂你改了什么、历史是什么会提交只是第一步&#xff0c;会"读"历史才是真的用上了 Git。这篇教你把 log 和 diff 玩出花来。git log&#xff1a;查看提交历史 git log默认输出太详细&#xff0c;通常用这些参数来精简&…...

5分钟学会NCM文件转换:ncmdumpGUI让你的网易云音乐随处播放

5分钟学会NCM文件转换&#xff1a;ncmdumpGUI让你的网易云音乐随处播放 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换&#xff0c;Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你是否曾经在网易云音乐下载了心爱的歌…...

Joy-Con Toolkit:任天堂手柄全能管理解决方案

Joy-Con Toolkit&#xff1a;任天堂手柄全能管理解决方案 【免费下载链接】jc_toolkit Joy-Con Toolkit 项目地址: https://gitcode.com/gh_mirrors/jc/jc_toolkit 核心价值&#xff1a;重新定义手柄控制体验 Joy-Con Toolkit作为开源手柄管理领域的创新工具&#xff0…...

Ostrakon-VL-8B在VMware虚拟机中的一站式部署与性能调优

Ostrakon-VL-8B在VMware虚拟机中的一站式部署与性能调优 想在本地隔离环境里跑通一个强大的多模态大模型&#xff0c;比如Ostrakon-VL-8B&#xff0c;但又不想折腾物理机或者担心影响主系统&#xff1f;VMware虚拟机是个不错的选择。不过&#xff0c;在虚拟机里部署AI应用&…...

Tencent Hunyuan3D-1.0日志轮转配置:防止磁盘空间耗尽的日志管理方案

Tencent Hunyuan3D-1.0日志轮转配置&#xff1a;防止磁盘空间耗尽的日志管理方案 【免费下载链接】Hunyuan3D-1 腾讯开源的Hunyuan3D-1项目&#xff0c;创新提出两阶段3D生成方法&#xff0c;实现快速、高质量的文本到3D和图像到3D转换&#xff0c;融合Hunyuan-DiT模型&#xf…...

OpenClaw飞书机器人进阶:Qwen3.5-9B图片问答自动回复

OpenClaw飞书机器人进阶&#xff1a;Qwen3.5-9B图片问答自动回复 1. 为什么选择OpenClaw飞书Qwen3.5-9B组合&#xff1f; 去年我们团队内部遇到一个典型问题&#xff1a;产品文档和功能说明分散在各个Confluence页面&#xff0c;新同事遇到界面不熟悉时&#xff0c;老员工需要…...