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

Java | CompletableFuture详解

关注:CodingTechWork

CompletableFuture 概述

介绍

  CompletableFutureJava 8 引入的一个非常强大的类,属于 java.util.concurrent 包。它是用于异步编程的一个工具,可以帮助我们更方便地处理并发任务。与传统的线程池或 Future 对比,CompletableFuture 提供了更多灵活性和组合功能,使得异步编程更加简单和易于维护。
  CompletableFuture主要用于异步操作和组合多个异步任务。它可以通过执行非阻塞的操作来避免阻塞主线程,从而提高程序的性能和响应速度。
  CompletableFuture实现了 FutureCompletionStage 接口。

优势

相比传统的 Future 接口,具有以下核心优势:

  • 支持非阻塞的异步操作
  • 提供链式调用和组合操作的能力
  • 内置完善的异常处理机制
  • 支持函数式编程风格

与传统 Future 对比

特性FutureCompletableFuture
结果获取阻塞 get() 方法支持回调通知
链式调用不支持支持多级流水线处理
异常处理需要 try-catch内置异常传播机制
组合操作手动实现提供多种组合方法
手动完成不支持支持 complete() 方法

核心方法

supplyAsync()

用于执行一个异步任务并返回一个结果。它接受一个 Supplier,并在后台线程执行该任务。

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {return 42;
});

runAsync()

用于执行一个异步任务,但不返回结果。它接受一个Runnable,并在后台线程执行该任务。

CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {System.out.println("Task executed");
});

thenApply()

用于将前一个计算的结果转换为另一个结果。它接受一个Function,该函数作用于先前计算的结果,并返回一个新的CompletableFuture

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 5).thenApply(result -> result * 2);

thenAccept()

用于处理前一个计算结果并返回Void。它接受一个Consumer,用于对先前的结果执行操作。

CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> 5).thenAccept(result -> System.out.println(result));

thenCombine()

用于将两个CompletableFuture的结果结合成一个新的结果。它接受两个CompletableFuture和一个BiFunction

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 5);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 10);CompletableFuture<Integer> combined = future1.thenCombine(future2, (result1, result2) -> result1 + result2);

thenCompose()

用于将两个异步操作串联起来,第二个任务依赖第一个任务的结果。它接受一个Function,返回一个新的CompletableFuture

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 5).thenCompose(result -> CompletableFuture.supplyAsync(() -> result * 2));

allOf()

用于组合多个CompletableFuture,并等待它们全部完成。返回一个新的 CompletableFuture,它完成时表示所有的CompletableFuture都已完成。

CompletableFuture<Void> future1 = CompletableFuture.supplyAsync(() -> 5);
CompletableFuture<Void> future2 = CompletableFuture.supplyAsync(() -> 10);CompletableFuture<Void> allOf = CompletableFuture.allOf(future1, future2);

anyOf()

用于组合多个CompletableFuture,并等待任意一个任务完成。返回一个新的 CompletableFuture,该CompletableFuture完成时表示至少有一个任务已完成。

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 5);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 10);CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future1, future2);

exceptionally()

用于在异步任务执行过程中发生异常时处理异常。它接受一个Function,如果任务执行失败(抛出异常),则返回一个备用值。

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {if (true) throw new RuntimeException("Error");return 5;})// 处理异常,返回-1.exceptionally(ex -> -1); 

whenComplete()

用于在任务完成后进行额外操作,不论任务是正常完成还是异常完成。它接受一个 BiConsumer,用于处理结果和异常。

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 5).whenComplete((result, ex) -> {if (ex == null) {System.out.println("Completed with result: " + result);} else {System.out.println("Completed with exception: " + ex.getMessage());}});

supplyAsync()和runAsync() 区别

CompletableFuture.supplyAsync() 和 CompletableFuture.runAsync() 都是用来异步执行任务的,但它们之间有一些关键区别,主要体现在是否返回结果以及如何处理任务:

返回值

  • supplyAsync()功能:该方法接受一个 Supplier 函数,Supplier 是一个能够返回结果的函数。它会异步执行任务并返回一个 CompletableFuture<T>,这个 CompletableFuture 可以通过 get() 等方法获取任务的返回值。
  • supplyAsync()适用场景:当你需要执行一个任务,并且希望获取这个任务的结果时,使用 supplyAsync()
  • runAsync()功能:该方法接受一个 Runnable函数,Runnable是一个没有返回值的任务。它会异步执行任务,但不会返回任何结果,因此返回的是一个CompletableFuture<Void>,意味着你只能知道任务是否完成,但无法直接获取任务的结果。
  • runAsync()适用场景:当你只需要执行任务,但不关心返回结果时,使用runAsync()

任务执行

  • supplyAsync():异步任务执行后会返回一个值,通常使用 thenApply()、thenAccept() 等方法来处理返回值。
  • runAsync():执行的是没有返回值的任务,通常用 thenRun() 来处理任务完成后的操作。

使用场景

  • supplyAsync():适用于有返回值的任务,例如你需要异步计算某个结果。
  • runAsync():适用于没有返回值的任务,例如日志记录、状态更新等。

技术原理

创建异步任务

// 使用默认 ForkJoinPool
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> "Result");// 指定自定义线程池
ExecutorService executor = Executors.newFixedThreadPool(2);
CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(() -> {// 业务逻辑return "Custom Result";
}, executor);

结果处理

同步回调

// thenApply: 同步转换结果
cf.thenApply(s -> s + " processed").thenAccept(System.out::println);// thenAccept: 同步消费结果
cf.thenAccept(result -> {System.out.println("Received: " + result);
});

异步回调

// thenApplyAsync: 异步转换
cf.thenApplyAsync(s -> {// 在 ForkJoinPool 异步执行return s.toUpperCase();
});// 指定自定义线程池
cf.thenAcceptAsync(result -> {System.out.println("Async processing");
}, executor);

组合操作

串行组合

// 查询用户信息,然后根据用户ID查询订单信息(串行执行)
CompletableFuture<String> cf = queryUserInfo()// 使用 thenCompose 实现串行组合.thenCompose(user -> queryOrder(user.getId())); 

并行组合

// 并行查询服务A和服务B
// 查询服务A
CompletableFuture<String> cf1 = queryServiceA(); 
// 查询服务B
CompletableFuture<String> cf2 = queryServiceB(); // 合并两个结果(并行执行,结果合并)
CompletableFuture<String> combined = cf1// 使用 thenCombine 合并两个任务的结果.thenCombine(cf2, (res1, res2) -> res1 + " & " + res2); // 任意一个完成即返回(并行执行,取最先完成的结果)
// 使用 anyOf 实现快速返回
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(cf1, cf2); 

异常处理

// 异常处理:捕获异常并返回默认值
cf.exceptionally(ex -> {// 打印异常信息System.err.println("Error: " + ex.getMessage()); // 返回默认值return "default value"; 
});// 异常处理:捕获异常并返回 fallback 值
cf.handle((result, ex) -> {// 如果有异常if (ex != null) { // 返回 fallback 值return "fallback"; }// 否则返回正常结果return result; 
});

超时控制

// 超时控制:如果任务在指定时间内未完成,返回默认值
// 1秒后未完成则返回 "default"
cf.completeOnTimeout("default", 1, TimeUnit.SECONDS); 

典型应用场景

并行任务处理

// 并行处理多个请求
List<CompletableFuture<String>> futures = requests.stream().map(request -> // 对每个请求异步处理CompletableFuture.supplyAsync(() -> process(request), executor)) // 收集所有任务.collect(Collectors.toList()); // 等待所有任务完成
CompletableFuture<Void> allDone = CompletableFuture// 使用 allOf 等待所有任务完成.allOf(futures.toArray(new CompletableFuture[0])); 

服务调用编排

// 服务调用编排:依次执行多个异步任务
CompletableFuture<Order> orderFuture = // 获取用户信息getUserProfile() // 验证地址.thenCompose(user -> validateAddress(user)) // 创建订单.thenCompose(address -> createOrder(address)) // 异常时创建备用订单.exceptionally(ex -> createFallbackOrder()); 

异步结果聚合

// 异步结果聚合:合并两个异步任务的结果
CompletableFuture<Integer> total = // 任务1:返回10CompletableFuture.supplyAsync(() -> 10) // 任务2:返回20,合并结果为30.thenCombine(CompletableFuture.supplyAsync(() -> 20), Integer::sum); 

demo:电商订单处理

场景需求

  1. 并行查询用户信息和商品库存
  2. 验证地址有效性
  3. 组合结果创建订单
  4. 记录操作日志

实现代码

import java.util.concurrent.*;public class OrderService {private final ExecutorService executorService;// 构造函数接受线程池大小参数public OrderService(int poolSize) {// 创建一个自定义线程池,大小为 poolSizethis.executorService = Executors.newFixedThreadPool(poolSize);System.out.println("Thread pool initialized with size: " + poolSize);}// 线程池大小配置方法public void setThreadPoolSize(int poolSize) {// 关闭现有线程池并创建一个新的线程池shutdown();  // 关闭旧线程池this.executorService = Executors.newFixedThreadPool(poolSize);  // 创建新的线程池System.out.println("Thread pool resized to: " + poolSize);}// 获取当前线程池大小public int getThreadPoolSize() {if (executorService instanceof ThreadPoolExecutor) {return ((ThreadPoolExecutor) executorService).getCorePoolSize();}return -1; // 如果没有获取到线程池大小,则返回 -1}public CompletableFuture<OrderResult> createOrderAsync(OrderRequest request) {// 并行查询用户信息和库存信息CompletableFuture<UserInfo> userFuture = queryUserAsync(request.getUserId());CompletableFuture<Inventory> inventoryFuture = queryInventoryAsync(request.getSkuId());// 使用 thenCombine 合并两个异步结果return userFuture.thenCombine(inventoryFuture, (user, inventory) -> {// 验证用户地址validateAddress(user.getAddress());// 检查库存是否足够checkInventory(inventory);// 根据用户信息、库存信息和订单请求生成订单return generateOrder(user, inventory, request);})// 使用 thenCompose 对生成的订单进行进一步处理.thenCompose(order -> {// 异步保存订单return saveOrderAsync(order)// 保存成功后,发送通知.thenApply(savedOrder -> sendNotification(savedOrder));})// 处理最终结果,或者处理异常.handle((result, ex) -> {// 如果出现异常,记录错误并返回失败的结果if (ex != null) {log.error("Order failed", ex);return OrderResult.failure(ex.getMessage());}// 如果成功,返回成功的结果return OrderResult.success(result);});}// 异步查询用户信息,使用自定义线程池private CompletableFuture<UserInfo> queryUserAsync(String userId) {return CompletableFuture.supplyAsync(() -> userService.getUser(userId), executorService);}// 异步查询库存信息,使用自定义线程池private CompletableFuture<Inventory> queryInventoryAsync(String skuId) {return CompletableFuture.supplyAsync(() -> inventoryService.getStock(skuId), executorService);}// 验证用户地址是否合法private void validateAddress(String address) {if (address == null || address.isEmpty()) {throw new IllegalArgumentException("Address is invalid.");}// 进一步的地址验证逻辑}// 检查库存是否足够private void checkInventory(Inventory inventory) {if (inventory == null || inventory.getStock() <= 0) {throw new IllegalArgumentException("Insufficient inventory.");}}// 根据用户和库存信息生成订单private Order generateOrder(UserInfo user, Inventory inventory, OrderRequest request) {Order order = new Order();order.setUserId(user.getUserId());order.setSkuId(request.getSkuId());order.setQuantity(request.getQuantity());order.setTotalPrice(inventory.getPrice() * request.getQuantity());order.setShippingAddress(user.getAddress());order.setStatus(OrderStatus.PENDING);return order;}// 异步保存订单,使用自定义线程池private CompletableFuture<Order> saveOrderAsync(Order order) {return CompletableFuture.supplyAsync(() -> orderService.saveOrder(order), executorService);}// 发送订单通知private String sendNotification(Order order) {notificationService.sendOrderConfirmation(order);return "Order placed successfully!";}// 关闭线程池public void shutdown() {if (executorService != null && !executorService.isShutdown()) {executorService.shutdown();System.out.println("Thread pool shut down gracefully.");}}// 强制关闭线程池public void shutdownNow() {if (executorService != null && !executorService.isShutdown()) {executorService.shutdownNow();System.out.println("Thread pool shut down immediately.");}}// 线程池是否已关闭public boolean isShutdown() {return executorService.isShutdown();}// 主方法示例public static void main(String[] args) {// 初始化 OrderService 并传入线程池大小OrderService orderService = new OrderService(5);// 获取并输出当前线程池大小int poolSize = orderService.getThreadPoolSize();System.out.println("Current thread pool size: " + poolSize);// 假设创建一个订单请求对象OrderRequest orderRequest = new OrderRequest("user123", "sku456", 2);orderService.createOrderAsync(orderRequest).thenAccept(result -> {System.out.println(result.getMessage());});// 动态调整线程池大小orderService.setThreadPoolSize(10);System.out.println("Updated thread pool size: " + orderService.getThreadPoolSize());// 关闭线程池orderService.shutdown();}
}

输出结果

Thread pool initialized with size: 5
Current thread pool size: 5
Order placed successfully!
Thread pool resized to: 10
Updated thread pool size: 10
Thread pool shut down gracefully.

最佳实践与注意事项

线程池选择策略

  • CPU密集型任务使用有界线程池
  • IO密集型任务使用缓存线程池
  • 避免混合使用不同任务类型
    资源管理
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {CompletableFuture.runAsync(() -> task(), executor);
}

调试技巧

  • 使用 thenApplyAsync 添加日志点
  • 包装异步操作添加跟踪ID
cf.thenApplyAsync(result -> {log.debug("[Trace-{}] Step completed", traceId);return result;
});

性能优化

  • 避免过度嵌套回调
  • 及时关闭自定义线程池
  • 使用CompletableFuture#join()谨慎

总结

CompletableFuture为 Java 异步编程提供了强大支持,特别适用于:

  • 需要编排多个异步操作的场景
  • 实现非阻塞的响应式系统
  • 需要精细控制任务执行顺序和依赖关系
  • 构建高并发、低延迟的服务

相关文章:

Java | CompletableFuture详解

关注&#xff1a;CodingTechWork CompletableFuture 概述 介绍 CompletableFuture是 Java 8 引入的一个非常强大的类&#xff0c;属于 java.util.concurrent 包。它是用于异步编程的一个工具&#xff0c;可以帮助我们更方便地处理并发任务。与传统的线程池或 Future 对比&…...

【背包问题】二维费用的背包问题

目录 二维费用的背包问题详解 总结&#xff1a; 空间优化&#xff1a; 1. 状态定义 2. 状态转移方程 3. 初始化 4. 遍历顺序 5. 时间复杂度 例题 1&#xff0c;一和零 2&#xff0c;盈利计划 二维费用的背包问题详解 前面讲到的01背包中&#xff0c;对物品的限定条件…...

Golang 并发机制-5:详解syn包同步原语

并发性是现代软件开发的一个基本方面&#xff0c;Go&#xff08;也称为Golang&#xff09;为并发编程提供了一组健壮的工具。Go语言中用于管理并发性的重要包之一是“sync”包。在本文中&#xff0c;我们将概述“sync”包&#xff0c;并深入研究其最重要的同步原语之一&#xf…...

实验六 项目二 简易信号发生器的设计与实现 (HEU)

声明&#xff1a;代码部分使用了AI工具 实验六 综合考核 Quartus 18.0 FPGA 5CSXFC6D6F31C6N 1. 实验项目 要求利用硬件描述语言Verilog&#xff08;或VHDL&#xff09;、图形描述方式、IP核&#xff0c;结合数字系统设计方法&#xff0c;在Quartus开发环境下&#xff…...

如何用微信小程序写春联

​ 生活没有模板,只需心灯一盏。 如果笑能让你释然,那就开怀一笑;如果哭能让你减压,那就让泪水流下来。如果沉默是金,那就不用解释;如果放下能更好地前行,就别再扛着。 一、引入 Vant UI 1、通过 npm 安装 npm i @vant/weapp -S --production​​ 2、修改 app.json …...

LabVIEW无人机航线控制系统

介绍了一种无人机航线控制系统&#xff0c;该系统利用LabVIEW软件与MPU6050九轴传感器相结合&#xff0c;实现无人机飞行高度、速度、俯仰角和滚动角的实时监控。系统通过虚拟仪器技术&#xff0c;有效实现了数据的采集、处理及回放&#xff0c;极大提高了无人机航线的控制精度…...

C++哈希表深度解析:从原理到实现,全面掌握高效键值对存储

目录 一、核心组件与原理 1. 哈希函数&#xff08;Hash Function&#xff09; 2. 冲突解决&#xff08;Collision Resolution&#xff09; 3. 负载因子&#xff08;Load Factor&#xff09;与扩容 二、C实现&#xff1a;std::unordered_map 1. 模板参数 2. 关键操作与复…...

Vue.js组件开发-实现字母向上浮动

使用Vue实现字母向上浮动的效果 实现步骤 创建Vue项目&#xff1a;使用Vue CLI来创建一个新的Vue项目。定义组件结构&#xff1a;在组件的模板中&#xff0c;定义包含字母的元素。添加样式&#xff1a;使用CSS动画来实现字母向上浮动的效果。绑定动画类&#xff1a;在Vue组件…...

自研有限元软件与ANSYS精度对比-Bar2D2Node二维杆单元模型-四连杆实例

目录 1、四连杆工程实例以及手算求解 2、四连杆的自研有限元软件求解 2.1、选择单元类型 2.2、导入四连杆工程 2.3、节点坐标定义 2.4、单元连接关系、材料定义 2.5、约束定义 2.6、外载定义 2.7、矩阵求解 2.8、变形云图展示 2.9、节点位移 2.10、单元应力 2.11、…...

04树 + 堆 + 优先队列 + 图(D1_树(D11_伸展树))

目录 一、基本介绍 二、伸展操作 1. 左右情况的伸展 2. 左左情况的伸展 3. 右左情况的伸展 4. 右右情况的伸展 三、其它操作 1. 插入 2. 删除 四、代码实现 一、基本介绍 伸展树是一种二叉搜索树&#xff0c;伸展树也是一种平衡树&#xff0c;不过伸展树并不像AVL树那…...

c语言练习题【数据类型、递归、双向链表快速排序】

练习1&#xff1a;数据类型 请写出以下几个数据的数据类型 整数 a a 的地址 存放a的数组 b 存放a的地址的数组 b的地址 c的地址 指向 printf 函数的指针 d 存放 d的数组 整数 a 的类型 数据类型是 int a 的地址 数据类型是 int*&#xff08;指向 int 类型的指针&#xff09; …...

SliverAppBar的功能和用法

文章目录 1 概念介绍2 使用方法3 示例代码 我们在上一章回中介绍了SliverGrid组件相关的内容&#xff0c;本章回中将介绍SliverAppBar组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1 概念介绍 我们在本章回中介绍的SliverAppBar和普通的AppBar类似&#xff0c;它们的…...

五、定时器实现呼吸灯

5.1 定时器与计数器简介 定时器是一种通过对内部时钟脉冲计数来测量时间间隔的模块。它的核心是一个递增或递减的寄存器&#xff08;计数器值&#xff09;。如果系统时钟为 1 MHz&#xff0c;定时器每 1 μs 计数一次。 计数器是一种对外部事件&#xff08;如脉冲信号&#xff…...

Elasticsearch的索引生命周期管理

目录 说明零、参考一、ILM的基本概念二、ILM的实践步骤Elasticsearch ILM策略中的“最小年龄”是如何计算的&#xff1f;如何监控和调整Elasticsearch ILM策略的性能&#xff1f; 1. **监控性能**使用/_cat/thread_pool API基本请求格式请求特定线程池的信息响应内容 2. **调整…...

【大模型理论篇】最近大火的DeepSeek-R1初探系列1

1. 背景介绍 这一整个春节&#xff0c;被DeepSeek-R1刷屏。各种铺天盖地的新闻以及老板发的相关信息&#xff0c;着实感受到DeepSeek-R1在国外出圈的震撼。 DeepSeek推出了新的推理模型&#xff1a;DeepSeek-R1-Zero 和 DeepSeek-R1。DeepSeek-R1-Zero 是一个在没有经过监督微调…...

【数据结构】(4) 线性表 List

一、什么是线性表 线性表就是 n 个相同类型元素的有限序列&#xff0c;每一个元素只有一个前驱和后继&#xff08;除了第一个和最后一个元素&#xff09;。 数据结构中&#xff0c;常见的线性表有&#xff1a;顺序表、链表、栈、队列。 二、什么是 List List 是 Java 中的线性…...

【C++ STL】vector容器详解:从入门到精通

【C STL】vector容器详解&#xff1a;从入门到精通 摘要&#xff1a;本文深入讲解C STL中vector容器的使用方法&#xff0c;涵盖常用函数、代码示例及注意事项&#xff0c;助你快速掌握动态数组的核心操作&#xff01; 一、vector概述 vector是C标准模板库&#xff08;STL&am…...

OpenAI推出Deep Research带给我们怎样的启示

OpenAI 又发新产品了&#xff0c;这次是面向深度研究领域的智能体产品 ——「Deep Research」&#xff0c;貌似被逼无奈的节奏… 在技术方面&#xff0c;Deep Research搭载了优化后o3模型并通过端到端强化学习在多个领域的复杂浏览和推理任务上进行了训练。因没有更多的技术暴露…...

洛谷[USACO08DEC] Patting Heads S

题目传送门 题目难度&#xff1a;普及/提高一 题面翻译 今天是贝茜的生日&#xff0c;为了庆祝自己的生日&#xff0c;贝茜邀你来玩一个游戏。 贝茜让 N N N ( 1 ≤ N ≤ 1 0 5 1\leq N\leq 10^5 1≤N≤105) 头奶牛坐成一个圈。除了 1 1 1 号与 N N N 号奶牛外&#xff0…...

CSS 溢出内容处理:从基础到实战

CSS 溢出内容处理&#xff1a;从基础到实战 1. 什么是溢出&#xff1f;示例代码&#xff1a;默认溢出行为 2. 使用 overflow 属性控制溢出2.1 使用 overflow: hidden 裁剪内容示例代码&#xff1a;裁剪溢出内容 2.2 使用 overflow: scroll 显示滚动条示例代码&#xff1a;显示滚…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践

在 Kubernetes 集群中&#xff0c;如何在保障应用高可用的同时有效地管理资源&#xff0c;一直是运维人员和开发者关注的重点。随着微服务架构的普及&#xff0c;集群内各个服务的负载波动日趋明显&#xff0c;传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...