高并发架构设计:从 Java Callable 到 CompletableFuture 的进阶修炼

server/2024/12/22 17:44:49/

前言

在现代的分布式系统中,高并发性能是一个决定系统能否成功的关键因素。而 Java 作为主流的后端开发语言,也提供了许多强大的工具来帮助我们处理并发任务。今天,我们将通过两个关键工具来讲解高并发架构设计的技巧:CallableCompletableFuture

通过这篇文章,你将从基础了解这些工具,逐步进入进阶用法,最后掌握如何在复杂的并发环境中使用它们来设计高效、可扩展的系统架构。


一、Java Callable 的基础:为并发任务加油

首先,让我们从 Java 中的 Callable 接口开始。这是 Java 并发编程中的一个基础接口,通常与 ExecutorService 配合使用来处理需要返回值的异步任务。

1. Callable 的基本用法

CallableRunnable 相似,不同的是 Callable 允许任务有返回值,且可以抛出异常。其基本结构如下:

java">import java.util.concurrent.Callable;public class MyTask implements Callable<String> {@Overridepublic String call() throws Exception {// 模拟耗时任务Thread.sleep(1000);return "Task Completed";}
}

call() 方法中,我们模拟了一个耗时的任务,任务完成后返回一个 String 类型的结果。

2. 如何使用 ExecutorService 执行 Callable

通过 ExecutorService,我们可以轻松地提交多个 Callable 任务,并获取其返回值。

java">import java.util.concurrent.*;public class CallableExample {public static void main(String[] args) throws InterruptedException, ExecutionException {ExecutorService executor = Executors.newFixedThreadPool(2);Callable<String> task1 = new MyTask();Callable<String> task2 = new MyTask();Future<String> future1 = executor.submit(task1);Future<String> future2 = executor.submit(task2);System.out.println(future1.get());  // 获取任务1的返回值System.out.println(future2.get());  // 获取任务2的返回值executor.shutdown();}
}

在这个例子中,我们创建了两个 Callable 任务,并通过 ExecutorService 提交执行。使用 Future.get() 方法,我们可以获取每个任务的返回值。


二、CompletableFuture 的强大功能:非阻塞异步编程

尽管 CallableFuture 已经能够满足大多数的并发需求,但当面对复杂的异步任务时,我们需要更强大的工具。这时,CompletableFuture 就登场了!

CompletableFuture 是 Java 8 引入的一个新的并发工具,它提供了比 Future 更加强大的功能,包括链式调用、非阻塞操作和并行任务组合等。

1. CompletableFuture 的基础用法

CompletableFuture 提供了非常简洁的 API 来处理异步任务。通过 supplyAsync() 方法,我们可以提交一个异步任务,并使用 thenApply() 来处理其返回结果。

java">import java.util.concurrent.*;public class CompletableFutureExample {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {// 模拟耗时任务try {Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}return "Task Completed";});future.thenApply(result -> {System.out.println(result);  // 处理任务返回值return result;});// 等待任务完成并获取结果future.get();}
}

在这个示例中,supplyAsync() 方法将一个异步任务提交给 CompletableFuture,并且使用 thenApply() 来处理任务的返回结果。get() 方法会等待任务完成并返回结果。

2. 链式调用与多个异步任务的组合

CompletableFuture 的一个重要特点是,它支持链式调用,可以轻松地将多个异步任务组合成一个流水线。这对于高并发系统中的多步骤任务处理非常有用。

java">CompletableFuture.supplyAsync(() -> {// 第一步:模拟耗时任务1return "Task 1 Completed";
})
.thenApply(result -> {// 第二步:基于第一步的结果处理return result + " and Task 2 Completed";
})
.thenAccept(result -> {// 第三步:最后一步,处理最终结果System.out.println(result);
});

通过 thenApply()thenAccept() 等方法,我们可以灵活地将多个任务按顺序执行,并处理每个任务的返回结果。

3. 多个任务并行执行

CompletableFuture 还支持并行执行多个任务,并将它们的结果合并。例如,使用 allOf()anyOf() 可以等待多个任务的完成。

java">CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {// 模拟任务1
});
CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {// 模拟任务2
});CompletableFuture.allOf(future1, future2).join();  // 等待所有任务完成

在这个例子中,我们使用 allOf() 来等待多个任务同时完成。join() 方法会阻塞当前线程直到所有任务完成。


三、进阶技巧:结合 Callable 和 CompletableFuture

在实际的项目中,我们往往需要同时使用 CallableCompletableFuture 来构建更加复杂的高并发任务。比如,使用 ExecutorService 提交 Callable 任务,再将其结果转换为 CompletableFuture 来实现更复杂的并发逻辑。

java">ExecutorService executor = Executors.newFixedThreadPool(2);Callable<String> task1 = () -> {// 模拟耗时任务1Thread.sleep(1000);return "Task 1 Completed";
};Callable<String> task2 = () -> {// 模拟耗时任务2Thread.sleep(500);return "Task 2 Completed";
};CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {try {return executor.submit(task1).get();  // 从 Callable 获取返回值} catch (Exception e) {throw new RuntimeException(e);}
});CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {try {return executor.submit(task2).get();  // 从 Callable 获取返回值} catch (Exception e) {throw new RuntimeException(e);}
});CompletableFuture.allOf(future1, future2).join();  // 等待两个任务都完成

在这个例子中,我们使用了 ExecutorService 提交 Callable 任务,然后将其结果包装到 CompletableFuture 中,实现了更加灵活的并发任务组合。


四、总结:高效并发架构的终极武器

通过学习从 CallableCompletableFuture 的演变,我们了解了 Java 提供的强大并发工具。在高并发架构设计中,Callable 适合用来处理需要返回结果的简单任务,而 CompletableFuture 则提供了更强大的功能,能够处理更复杂的异步操作和任务组合。

掌握了这些工具,你可以在高并发环境下更加优雅地设计系统架构,处理多个异步任务,避免阻塞,并充分利用多核处理器的能力,从而让你的系统更具扩展性和性能。

希望这篇文章能为你的并发编程之路提供帮助,带你从基础到进阶,修炼出一套高效的并发架构设计方案!


http://www.ppmy.cn/server/152282.html

相关文章

vue3中的ref与reactive

摘要 在vue3直接定义变量不是响应式数据 在vue3中定义变量更改变量页面是显示不出来的 在按钮中绑定一个函数&#xff0c;当我点击它的时候发生改变str值 点击前 点击后 点击后控制台显示更改数据&#xff0c;而页面中不显示数据&#xff0c;这就是vue3没触发响应式 使用re…

mac 安装graalvm

Download GraalVM 上面链接选择jdk的版本 以及系统的环境下载graalvm的tar包 解压tar包 tar -xzf graalvm-jdk-<version>_macos-<architecture>.tar.gz 移入java的文件夹目录 sudo mv graalvm-jdk-<version> /Library/Java/JavaVirtualMachines 设置环境变…

Leetcode 串联所有单词的子串

算法思想&#xff08;中文解释&#xff09; 这道题目要求我们在字符串 s 中找到所有子串&#xff0c;这些子串是字符串数组 words 中所有单词的串联&#xff0c;并且每个单词只能使用一次&#xff0c;且顺序可以任意。下面是代码的算法思想&#xff1a; 1. 核心思路 分解问题…

三、使用langchain搭建RAG:金融问答机器人--检索增强生成

经过前面2节数据准备后&#xff0c;现在来构建检索 加载向量数据库 from langchain.vectorstores import Chroma from langchain_huggingface import HuggingFaceEmbeddings import os# 定义 Embeddings embeddings HuggingFaceEmbeddings(model_name"m3e-base")#…

信息安全管理与评估赛题第4套

全国职业院校技能大赛 高等职业教育组 信息安全管理与评估 赛题四 模块一 网络平台搭建与设备安全防护 1 赛项时间 共计180分钟。 2 赛项信息 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段 网络平台搭建与设备安全防护 任务1 网络平台搭建 XX:XX- XX:XX 50 任务2…

视频点播系统|Java|SSM|VUE| 前后端分离

【技术栈】 1⃣️&#xff1a;架构: B/S、MVC 2⃣️&#xff1a;系统环境&#xff1a;Windowsh/Mac 3⃣️&#xff1a;开发环境&#xff1a;IDEA、JDK1.8、Maven、Mysql5.7 4⃣️&#xff1a;技术栈&#xff1a;Java、Mysql、SSM、Mybatis-Plus、VUE、jquery,html 5⃣️数据库可…

uni-app开发商品分类页面实现

目录 一:功能概述 二:功能实现 一:功能概述 这里商品分类按照常规的分类页面样式设计,左侧为一级分类,右侧为二级分类。在左侧切换不同的一级分类可以修改右侧的二级分类数据。右侧的展现方式是最上面显示对应的一级分类logo图片,下面展示二级分类的logo和名称。 二:…

SpringBoot 3.4.x踩坑记录及解决方案(持续更新)

废话 最近使用JDK17Spring Boot3.4.0 做新项目遇到的一些坑&#xff0c;记录并且给出一些实际的解决方案 一、集成Mybatis Plus 3.5.9的问题 第一&#xff1a;不能只引入mybatis-plus-spring-boot3-starter依赖了&#xff0c;需要配合mybatis-plus-jsqlparser <dependenc…