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

JAVA:异步任务处理类CompletableFuture让性能提升一倍

一、前言

  CompletableFuture 是 Java 8 引入的一个功能强大的类,用于异步编程。它表示一个可能尚未完成的计算的结果,你可以对其添加回调函数来在计算完成时执行某些操作。在 Spring Boot 应用中,CompletableFuture 可以用于提高应用的响应性和吞吐量。

二、为什么使用异步编程

  场景描述:进入用户个人中心,调用接口。接口需要返回用户基础信息、用户积分、用户等级等,假设用户基础信息查询耗时300ms,查询用户积分、用户等级分别耗时200ms,那么接口返回就需要700+ms了。那么我们如何去优化呢

  如果采用异步(多线程并行)形式,接口将以用户基础信息查询耗时300ms最慢的为主,接口性能提升一倍!查询任务越多,则其性能提升越大!

三、异步编程介绍

  在Java中,Callable、Runnable、Future和CompletableFuture是用于处理并发编程的重要接口和类。它们各自有不同的用途和特性,下面是对它们的简要介绍:

1. Callable
  Callable是一个接口,用于定义返回结果或抛出异常的任务。它类似于Runnable,但Runnable没有返回值且不能抛出受检异常。Callable接口中定义了一个call()方法,该方法可以返回一个值,并且可以抛出一个受检异常。

2. Runnable
  Runnable是一个接口,用于定义没有返回值且不抛出受检异常的任务。它只有一个run()方法,用于执行任务的代码。通常,Runnable对象会被传递给Thread对象的构造函数来创建新线程。

3. Future
  Future是一个接口,用于表示异步计算的结果。它是Java并发包java.util.concurrent的一部分。当你提交一个Callable任务给ExecutorService时,它会返回一个Future对象,该对象表示异步计算的结果。你可以使用Future的get()方法来等待计算完成并获取结果,或者使用isDone()方法来检查计算是否完成。

4. CompletableFuture
  CompletableFuture是Java 8中引入的一个类,实现了Future和CompletionStage接口。它提供了函数式编程的能力来处理异步编程,并允许你链式地组合多个异步操作。CompletableFuture提供了许多方法,如thenApply(), thenAccept(), thenCompose(), exceptionally()等,这些方法允许你定义当异步操作完成时应该执行的操作。

  CompletableFuture相对于Future的优势在于它提供了更丰富的API来处理异步计算的结果,并支持链式调用和组合多个异步操作。这使得编写异步代码更加简洁和直观。

四、CompletableFuture中的函数式编程

  在CompletableFuture类中的方法,很多都是Function函数式接口方法为入参,所以我们先要有一定的认识。

   Supplier<U>  // 生产者,没有入参,有返回结果Consumer<T>  // 消费者,有入参,但是没有返回结果Function<T,U>// 函数,有入参,又有返回结果

五、CompletableFuture核心方法介绍

5.1. 创建异步任务

   supplyAsync: 异步执行一个给定的Supplier函数,并返回一个新的CompletableFuture,其结果由Supplier决定。

  CompletableFuture<Void/Type> supplyAsync(Supplier<U> supplier)CompletableFuture<Void/Type> supplyAsync(Supplier<U> supplier, Executor executor):允许指定执行器。

   runAsync: 异步执行一个Runnable任务,由于没有返回值,所以返回的CompletableFuture类型为Void。

  CompletableFuture<Void> runAsync(Runnable runnable)CompletableFuture<Void> runAsync(Runnable runnable, Executor executor):允许指定执行器。

5.1.1. 代码示例

supplyAsync

CompletableFuture<String>future=CompletableFuture.supplyAsync(()->{System.out.println("compute test");return "test";
});String result = future.join();System.out.println("get result: " + result);

runAsync

CompletableFuture<Void> future = CompletableFuture.runAsync(()->{System.out.println("compute test");
});System.out.println("get result: " + future.join());

指定线程池

ExecutorService executorService = new ThreadPoolExecutor(2, 10, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));CompletableFuture<User> task1 = CompletableFuture.supplyAsync(()->{User userInfo = userService.getUserInfo(1);return userInfo;
}, executorService);// 获取结果
User user = task1.get();

5.2. 流式连接函数介绍

  流式连接函数(也称为组合函数)允许你以函数式编程的方式组合和链接多个异步操作。 假如:我有两个任务,任务2需要等任务1执行完成后,拿到任务1中的结果作为任务2的参数,这时候就需要用到流式连接函数。

①. thenApply 和 thenApplyAsync

  thenApply: 当前CompletableFuture计算完成时,应用给定的函数到其结果上,并返回表示该结果的新的CompletableFuture。

  thenApplyAsync: 与thenApply类似,但异步执行给定的函数。

②. thenAccept 和 thenAcceptAsync

  thenAccept: 当当前CompletableFuture计算完成时,执行给定的动作到其结果上,然后返回void。

  thenAcceptAsync: 与thenAccept类似,但异步执行给定的动作。

③. thenRun 和 thenRunAsync

  thenRun: 当当前CompletableFuture计算完成时,执行给定的动作,不关注其结果。

  thenRunAsync: 与thenRun类似,但异步执行给定的动作。

④. thenCombine 和 thenCombineAsync

  thenCombine: 接收另一个CompletableFuture,并返回一个新的CompletableFuture,该CompletableFuture在当前CompletableFuture和另一个CompletableFuture都完成计算后,使用它们的结果来计算值。

  thenCombineAsync: 与thenCombine类似,但异步执行给定的函数。

⑤. thenCompose 和 thenComposeAsync

  thenCompose: 当当前CompletableFuture计算完成时,应用给定的函数到其结果上,该函数返回一个新的CompletableFuture,并返回表示该新CompletableFuture的结果的CompletableFuture。

  thenComposeAsync: 与thenCompose类似,但异步执行给定的函数。

⑥. whenComplete 和 whenCompleteAsync

  whenComplete: 当当前CompletableFuture正常完成或出现异常时,执行给定的动作。动作有两个参数:结果(如果操作正常完成)或异常(如果抛出异常),以及一个表示该CompletableFuture的Throwable(如果操作抛出异常则为null)。

  whenCompleteAsync: 与whenComplete类似,但异步执行给定的动作。

⑦. handle 和 handleAsync

  handle: 当当前CompletableFuture正常完成或出现异常时,应用给定的函数到其结果或异常上,并返回一个新的CompletableFuture,其结果是函数的结果。

  handleAsync: 与handle类似,但异步执行给定的函数。

  注意带Async后缀的函数表示需要连接的后置任务会被单独提交到线程池中,从而相对前置任务来说是异步运行的。除此之外,两者没有其他区别。

  在使用Async后缀的方法时,你可以提供一个Executor作为可选参数来指定异步操作应在哪个线程上执行。如果未提供,则使用ForkJoinPool.commonPool()。

5.3. 流式连接核心函数代码示例

1. thenApply / thenAccept / thenRun

  这组函数主要用于连接前后有依赖的任务链。这里将thenApply / thenAccept / thenRun放在一起讲,因为这几个连接函数之间的唯一区别是提交的任务类型不一样。

区别如下:

  1.thenApply提交的任务类型需遵从Function签名,也就是有入参和返回值,其中入参为前置任务的结果。

  2.thenAccept提交的任务类型需遵从Consumer签名,也就是有入参但是没有返回值,其中入参为前置任务的结果。

  3.thenRun提交的任务类型需遵从Runnable签名,即没有入参也没有返回值。

代码示例:

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(()->{System.out.println("compute 1");return 1;
});CompletableFuture<Integer> future2 = future1.thenApply((p)->{System.out.println("compute 2");return p+10;
});
System.out.println("result: " + future2.join());

  注意的是,通过thenApply / thenAccept / thenRun连接的任务,当且仅当前置任务计算完成时,才会开始后置任务的计算。

应用场景总结:

  1. thenApply:当需要在异步操作的结果上执行额外的计算或转换时,使用 thenApply。

  2. thenAccept:当只需要消费异步操作的结果,而不关心新的结果或执行额外的任务时,使用 thenAccept。

  3. thenRun:当需要在异步操作完成后执行一个不依赖于其结果的任务时,使用 thenRun。

2. thenCombine

  thenCombine最大的不同是连接任务可以是一个独立的CompletableFuture,从而允许前后连接的两个任务可以并行执行(后置任务不需要等待前置任务执行完成),最后当两个任务均完成时,再将其结果同时传递给下游处理任务,从而得到最终结果

代码示例:
  假设我们有两个异步任务,一个用于获取用户的名字(nameFuture),另一个用于获取用户的年龄(ageFuture)。我们希望当这两个任务都完成后,将它们的结果组合成一个字符串,如 “Name: John, Age: 30”。


CompletableFuture<String> nameFuture = CompletableFuture.supplyAsync(() -> getUserName());  
CompletableFuture<Integer> ageFuture = CompletableFuture.supplyAsync(() -> getUserAge());  CompletableFuture<String> combinedFuture = nameFuture.thenCombine(ageFuture, (name, age) ->   "Name: " + name + ", Age: " + age  
);  combinedFuture.thenAccept(System.out::println); 
// 输出类似 "Name: John, Age: 30"

  thenAcceptBoth、thenAcceptBothAsync、runAfterBoth、runAfterBothAsync的作用与thenConbime类似,区别如下:

  1. thenAcceptBoth 和 thenAcceptBothAsync 用于处理两个异步操作的结果,但不返回新的结果。

  2. runAfterBoth 和 runAfterBothAsync 也用于处理两个异步操作的完成,但不关注它们的结果。

  3. thenCombine 用于处理两个异步操作的结果,并返回一个新的结果。

3. thenCompose

  thenCompose 的应用场景主要涉及到需要基于一个异步任务的结果来发起另一个异步任务的情况。它允许你将多个异步操作链接在一起,并以前一个操作的结果作为后一个操作的输入。

代码示例:

如果使用thenApply实现如下:CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(()->{System.out.println("compute 1");return 1;
});
CompletableFuture<CompletableFuture<Integer>> future2 =future1.thenApply((r)->CompletableFuture.supplyAsync(()->r+10));
System.out.println(future2.join().join());当连接的任务越多时,代码会变得越来越复杂,嵌套获取层级也越来越深。
使用thenCompose
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(()->{System.out.println("compute 1");return 1;
});
CompletableFuture<Integer> future2 = future1.thenCompose((r)->CompletableFuture.supplyAsync(()->r+10));
System.out.println(future2.join());

4. whenComplete

  whenComplete主要用于注入任务完成时的回调通知逻辑。这个解决了传统future在任务完成时,无法主动发起通知的问题。前置任务会将计算结果或者抛出的异常作为入参传递给回调通知函数。

代码示例:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {  // 模拟从数据库读取数据的异步操作  return "Data from database";  
});  future.whenComplete((result, exception) -> {  if (exception == null) {  // 操作成功,记录成功日志  System.out.println("Operation succeeded. Result: " + result);  } else {  // 操作失败,记录异常日志  System.err.println("Operation failed with exception: " + exception.getMessage());  }  // 在这里还可以执行其他与结果无关的操作,如清理资源、发送通知等  
});

5. handle

  handle与whenComplete的作用有些类似,但是handle接收的处理函数有返回值,而且返回值会影响最终获取的计算结果。

代码示例:

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(()->{System.out.println("compute 1");return 1;
});CompletableFuture<Integer> future2 = future1.handle((r, e)->{if(e != null){System.out.println("compute failed!");return r;} else {System.out.println("received result is " + r);return r + 10;}
});System.out.println("result: " + future2.join());

六、CompletableFuture中获取异步任务结果介绍

异步任务执行完成之后,需要获取结果,有如下一些方法:

  1. allOf 方法用于等待多个 CompletableFuture 任务全部完成。它接受一个 CompletableFuture 数组或列表作为参数,并返回一个新的 CompletableFuture。这个新的 CompletableFuture 会在所有给定的 CompletableFuture 都完成时完成,但它不包含任何原始任务的结果。

  2. anyOf 方法与 allOf 类似,但它只等待给定的 CompletableFuture 中的一个完成。它同样接受一个 CompletableFuture 数组或列表作为参数,并返回一个新的 CompletableFuture。这个新的 CompletableFuture 会在任何一个给定的 CompletableFuture 完成时完成,但它不包含任何原始任务的结果。

  3. join 方法用于等待 CompletableFuture 完成,并返回其结果(如果可用)。如果 CompletableFuture 尚未完成,则 join 会阻塞当前线程,直到它完成。如果 CompletableFuture 异常完成,则 join 会抛出与异常完成相对应的异常。

  4. get 方法与 join 类似,也用于等待 CompletableFuture 完成并返回其结果。但是,get 方法可以接收一个可选的超时参数和一个时间单位,以便在指定的时间内等待 CompletableFuture 完成。如果 CompletableFuture 在指定的时间内没有完成,则 get 方法会抛出 TimeoutException。另外,如果 CompletableFuture 异常完成,则 get 方法会抛出 ExecutionException(包装了原始异常)或 InterruptedException(如果当前线程在等待时被中断)。

  以上就是对CompletableFuture的一些详细介绍,以及一些常用api的代码示例,希望对你在项目进行性能方面的代码优化中有一定的作用。

相关文章:

JAVA:异步任务处理类CompletableFuture让性能提升一倍

一、前言 CompletableFuture 是 Java 8 引入的一个功能强大的类&#xff0c;用于异步编程。它表示一个可能尚未完成的计算的结果&#xff0c;你可以对其添加回调函数来在计算完成时执行某些操作。在 Spring Boot 应用中&#xff0c;CompletableFuture 可以用于提高应用的响应性…...

10Linux 进程管理学习笔记

Linux 进程管理 目录 文章目录 Linux 进程管理一.进程1.显示当前进程状态(ps)进程树(pstree)1.1实时显示进程信息(top)顶部概览信息&#xff1a;CPU 状态&#xff1a;内存状态&#xff1a;进程信息表头&#xff1a;进程列表&#xff1a;1.2(htop) 2.终止进程(kill)2.1通过名称…...

一些关于深度聚类以及部分对比学习的论文阅读笔记

目录 资料SwAV问题方法方法的创新点为什么有效有什么可以借鉴的地方聚类Multi-crop 代码 PCL代码 Feature Alignment and Uniformity for Test Time Adaptation代码 SimSiam 资料 深度聚类算法研究综述(很赞&#xff0c;从聚类方法和深度学习方法两个方面进行了总结&#xff0…...

【ARM-Linux篇】u-boot编译

一、u-boot简介 uboot是一种通用的引导加载程序&#xff0c;它可以用于多种嵌入式系统&#xff0c;支持多种操作系统&#xff0c;如Linux, Android,NetBSD等。uboot的主要作用是将操作系统内核从存储设备&#xff08;如Flash, SD卡等&#xff09;加载到内存中&#xff0c;并执…...

Lombok一文通

1、Lombok简介 作为java的忠实粉丝&#xff0c;但也不得不承认&#xff0c;java是一门比较啰嗦的语言&#xff0c;很多代码的编写远不如其他静态语言方便&#xff0c;更别说跟脚本语言比较了。 因此&#xff0c;lombok应运而生。 Lombok是一种工具库&#xff0c;它提供了一组…...

Seq2Seq模型:详述其发展历程、深远影响与结构深度剖析

Seq2Seq&#xff08;Sequence-to-Sequence&#xff09;模型是一种深度学习架构&#xff0c;专为处理从一个输入序列到一个输出序列的映射任务设计。这种模型最初应用于机器翻译任务&#xff0c;但因其灵活性和有效性&#xff0c;现已被广泛应用于自然语言处理&#xff08;NLP&a…...

公网如何访问内网?

公网和内网已经成为我们生活中不可或缺的存在。由于内网的安全性考虑&#xff0c;公网无法直接访问内网资源。如何实现公网访问内网呢&#xff1f;本文将介绍一种名为【天联】的私有通道技术&#xff0c;通过安全加密&#xff0c;保障数据传输的安全性。 【天联】私有通道技术 …...

手机定制开发_基于天玑900的5G安卓手机定制方案

手机定制方案基于联发科天玑900强劲旗舰八核2.4GHz处理器。这款处理器采用了6nm先进制程工艺&#xff0c;为用户带来了痛快淋漓的性能体验。不论是进行游戏还是日常娱乐&#xff0c;用户都能轻松驾驭。手机搭载了最新的Android 13操作系统&#xff0c;提高了数据读取的准确性&a…...

免费,C++蓝桥杯等级考试真题--第2级

C蓝桥杯等级考试真题–第2级...

panic 、asset、crash 的含义和区别

在编程中&#xff0c;“panic” 和 “assert” 都是用于处理错误和异常情况的机制&#xff0c;但在不同的编程语言和框架中有一些区别。 panic&#xff1a; 含义&#xff1a;通常表示程序发生了无法恢复的错误或异常情况&#xff0c;需要立即终止程序的执行。 用法&#xff1…...

解决Windows 10通过SSH连接Ubuntu 20.04时的“Permission Denied”错误

在使用SSH连接远程服务器时&#xff0c;我们经常可能遇到各种连接错误&#xff0c;其中“Permission denied, please try again”是较为常见的一种。本文将分享一次实际案例的解决过程&#xff0c;帮助你理解如何排查并解决这类问题。 问题描述 在尝试从Windows 10系统通过SS…...

Windows 下 PostgreSQL 图形化界面安装、配置详解

相信大家对PostgreSQL都不陌生吧&#xff0c;自从MySQL被Oracle所控制后&#xff0c;PostgreSQL就成为了国内去O的首选数据库了&#xff0c;并且PostgreSQL目前不受任何商业公司控制&#xff0c;所以国内很多厂商都是基于PostgreSQL做二次开发来实现数据库自主可控的目标(国内很…...

曾巩,散文的艺术与哲思

曾巩&#xff0c;字子固&#xff0c;世称南丰先生&#xff0c;南丰&#xff08;今江西&#xff09;人&#xff0c;生于北宋真宗天禧三年&#xff08;公元1019年&#xff09;&#xff0c;卒于北宋元丰六年&#xff08;公元1083年&#xff09;&#xff0c;享年64岁。他是中国北宋…...

【SpringBoot】怎么在一个大的SpringBoot项目中创建多个小的SpringBoot项目,从而形成子父依赖

父子项目工程创建 步骤 先创建父项目 具体操作步骤请看本文章&#xff1a;使用maven工程创建spring boot项目 创建子项目 file- project structure module–new module 剩下步骤请看创建父工程时的操作使用maven工程创建spring boot项目 应用 确认即可 之后创建启动类…...

vue3组件通信与props

title: vue3组件通信与props date: 2024/5/31 下午9:00:57 updated: 2024/5/31 下午9:00:57 categories: 前端开发 tags: Vue3组件Props详解生命周期数据通信模板语法Composition API单向数据流 Vue 3 组件基础 在 Vue 3 中&#xff0c;组件是构建用户界面的基本单位&#…...

并发和异步编程:详细概述

01 Concurrency and Asynchronous Programming: a Detailed Overview 并发和异步编程:详细概述 Asynchronous programming is one of those topics many programmers find confusing. You come to the point when you think you’ve got it, only to later realize that the …...

交易员摩拳擦掌,就在今年夏天,极端气候引爆商品?

有史以来最严重的高温炙烤下&#xff0c;从农业到能源到航运都可能受到严重负面影响&#xff0c;大宗商品市场波动将大幅加剧。 2024年有望成为有史以来最炎热的一年&#xff0c;随着北半球步入夏季&#xff0c;世界各地都将遭受由全球变暖造成的极端高温困扰。极端天气不仅给民…...

数据结构学习笔记

1. 数组 (Array) 定义 数组是一种线性数据结构&#xff0c;用于存储固定大小的相同类型元素集合。每个元素都有一个索引&#xff0c;用于快速访问。 特点 优点&#xff1a;访问速度快&#xff0c;通过索引直接访问O(1)时间复杂度。缺点&#xff1a;大小固定&#xff0c;插入…...

vscode导入自定义模块报错ModuleNotFoundError解决方案

问题描述 我的项目为great_gas_or_agents&#xff0c;目录结构如下&#xff1a; log_data_extract main.py math_algorithm 现在我运行main.py&#xff0c;报错&#xff1a;from math_algorithm.utils import parse_month_match_request&#xff0c;ModuleNotFoundError: No …...

go mod包管理与应用,常见错误排查方法

go mod包管理 go 中 包管理使用go mod 进行包管理 go mod init 项目名称 go mod init myproject_go生成的go.mod中有 module myproject_go 创建目录go_service 其下有两个go文件&#xff0c;go_request.go go_write.go . 根目录下有main.go入口文件。于是项目结构类似于&…...

数据结构作业

第1章 绪论 单选题 数据在计算机的存储器中表示时&#xff0c;逻辑上相邻的两个元素对应的物理地址也是相邻的&#xff0c;这种存储结构称之为________。 B. 顺序存储结构 算法指的是________。 D. 求解特定问题的指令有限序列 下面程序段的时间复杂度为&#xff1a;_______…...

项目纪实 | 版本升级操作get!GreatDB分布式升级过程详解

某客户项目现场&#xff0c;因其业务系统要用到数据库新版本中的功能特性&#xff0c;因此考虑升级现有数据库版本。在升级之前&#xff0c;万里数据库项目团队帮助客户在本地测试环境构造了相同的基础版本&#xff0c;导入部分生产数据&#xff0c;尽量复刻生产环境进行升级&a…...

富格林:应用正规技巧阻挠被骗

富格林悉知&#xff0c;随着如今入市现货黄金的朋友愈来愈多&#xff0c;不少投资者也慢慢开始重视起提高自身的正规投资技巧&#xff0c;希望能阻挠被骗更高效地在市场上获利。虽然目前黄金市场存在一定的受害风险&#xff0c;但只要投资者严格按照正规的交易规则来做单&#…...

【模型架构】学习RNN、LSTM、TextCNN和Transformer以及PyTorch代码实现

一、前言 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;模型架构的不断发展极大地推动了技术的进步。从早期的循环神经网络&#xff08;RNN&#xff09;到长短期记忆网络&#xff08;LSTM&#xff09;、Transformer再到当下火热的Mamba&#xff08;放在下一节&a…...

【LeetCode】38.外观数列

外观数列 题目描述&#xff1a; 「外观数列」是一个数位字符串序列&#xff0c;由递归公式定义&#xff1a; countAndSay(1) "1"countAndSay(n) 是 countAndSay(n-1) 的行程长度编码。 行程长度编码&#xff08;RLE&#xff09;是一种字符串压缩方法&#xff0c…...

如何解决Ubuntu中软件包安装时的404错误(无法安装gdb、cgddb等)

目录 问题描述 解决方法 1. 更新软件包列表 2. 使用--fix-missing选项 3. 更换软件源 4. 清理和修复包管理器 总结 在使用Ubuntu进行软件包安装时&#xff0c;有时可能会遇到404错误。这种错误通常是由于软件源中的某些包已经被移除或迁移到其他位置。本文将介绍几种解决…...

SpringBoot中MyBatisPlus的使用

MyBatis Plus 是 MyBatis 的增强工具&#xff0c;提供了许多强大的功能&#xff0c;简化了 MyBatis 的使用。下面是在 Spring Boot 中使用 MyBatis Plus 的步骤&#xff1a; 添加依赖&#xff1a;在 Maven 或 Gradle 的配置文件中添加 MyBatis Plus 的依赖。 配置数据源&#…...

前后端交互:axios 和 json;springboot 和 vue

vue 准备的 <template><div><button click"sendData">发送数据</button><button click"getData">接收</button><button click"refresh">刷新</button><br><ul v-if"questions&…...

前端技术专家岗(虚拟岗)

定位&#xff1a; 团队技术负责人、技术领导者&#xff1b;确保框架、工具的低门槛、高性能、可扩展&#xff1b; 素质要求&#xff1a; 具备架构设计能力&#xff1b;一个或者多个领域的技术专家&#xff1b;较为丰富的基础建设经验&#xff1b;项目管理能力、任务分解、协…...

redis windows环境下的部署安装

2024Redis windows安装、部署与环境变量 一、下载 Redis官网目前暂不支持Windows版本&#xff0c;只能从github中下载。 windows 64位系统下载redis路径&#xff1a;https://github.com/tporadowski/redis/releases&#xff0c;下载zip包。 目前Windows版本只更新到5.0的版本…...

大字体学生出勤记录系统网页HTML源码

源码介绍 上课需要一个个点名记录出勤情况&#xff0c;就借助AI制作了一个网页版学生出勤记录系统&#xff0c; 大字体显示学生姓名和照片&#xff0c;让坐在最后排学生也能看清楚&#xff0c;显示姓名同时会语音播报姓名&#xff0c; 操作很简单&#xff0c;先导入学生姓名…...

筛斗数据提取技术在企业成本预测中的应用

在当今的商业环境中&#xff0c;准确的成本预测对于企业的财务健康和战略规划至关重要。随着大数据和人工智能技术的飞速发展&#xff0c;数据提取技术已经成为企业进行成本预测的强大工具。本文将探讨数据提取技术如何帮助企业进行成本预测&#xff0c;并分析其对企业决策过程…...

enum编程入门:探索枚举类型的奥秘

enum编程入门&#xff1a;探索枚举类型的奥秘 在编程的世界里&#xff0c;enum&#xff08;枚举&#xff09;类型是一种特殊的数据类型&#xff0c;它允许我们为变量设置一组预定义的、有限的值。这种类型在很多编程语言中都得到了广泛的应用&#xff0c;为开发者提供了更加清…...

刷机 iPhone 进入恢复模式

文章目录 第 1 步&#xff1a;确保你有一台电脑&#xff08;Mac 或 PC&#xff09;第 2 步&#xff1a;将 iPhone 关机第 3 步&#xff1a;将 iPhone 置于恢复模式第 4 步&#xff1a;使用 Mac 或 PC 恢复 iPhone需要更多协助&#xff1f; 本文转载自&#xff1a;如果你忘记了 …...

计算属性和侦听器:为什么在某些情况下使用计算属性比使用methods更好,如何使用侦听器来监听数据的变化。

计算属性和methods的区别和使用场景 计算属性&#xff08;Computed properties&#xff09;是 Vue 中非常重要的一个功能&#xff0c;它有以下的优点&#xff1a; 数据缓存&#xff1a;计算属性基于它们的依赖进行缓存。只有在相关依赖发生变化时&#xff0c;才会重新求值。这…...

一文带你搞懂大事务的前因后果

引言 一文带你搞懂Spring事务上篇文章介绍了Spring事务相关内容&#xff0c;本文主要介绍业务开发中遇到的大事务问题。 https://github.com/WeiXiao-Hyy/blog 整理了Java,K8s,极客时间,设计模式等内容&#xff0c;欢迎Star! 什么是大事务 运行时间&#xff08;调用远程事务或…...

关系数据库:关系运算

文章目录 关系运算并&#xff08;Union&#xff09;差&#xff08;Difference&#xff09;交&#xff08;Intersection&#xff09;笛卡尔积&#xff08;Extended Cartesian Product&#xff09;投影&#xff08;projection&#xff09;选择&#xff08;Selection&#xff09;除…...

微信公众号开发(三):自动回复“你好”

上一篇做了服务器校验&#xff0c;但没有处理用户发来的消息&#xff0c;为了完成自动回复的功能&#xff0c;需要增加一些功能&#xff1a; 1、调整服务器校验函数&#xff1a; def verify_wechat(request):tokentokendatarequest.argssignaturedata.get(signature)timestamp…...

docker基本操作命令(3)

目录 1.Docker服务管理命令&#xff1a; 启动&#xff1a;systemctl start docker 停止&#xff1a;systemctl stop docker 重启&#xff1a;systemctl restart docker 开机自启&#xff1a;systemctl enable docker 查看docker版本&#xff1a; 2.镜像常用管理命令&…...

003 MySQL

文章目录 左外连接、右外连接 的区别where/having的区别执行顺序聚合 聚合函数MySQL约束事务一致性一致性的含义一致性在事务中的作用如何维护一致性 存储引擎 Innodb MyIsam区别事务的ACID属性数据库的隔离级别MySQL中的并发问题1. 锁等待和死锁2. 并发冲突3. 脏读、不可重复读…...

数据分析------统计学知识点(一)

1.在统计学中&#xff0c;均值分类有哪些&#xff1f; 算术均值&#xff1a;平均值&#xff0c;所有数值加总后除以数值的个数 几何均值&#xff1a;所有数值相乘后&#xff0c;再取其n次方根&#xff0c;n是数值的个数 调和均值&#xff1a;是数值倒数的算术均值的倒数 加…...

Apache Doris 基础 -- 数据表设计(分区分桶)

Versions: 2.1 本文档主要介绍了Doris的表创建和数据分区&#xff0c;以及表创建过程中可能遇到的问题和解决方案。 1、基本概念 在Doris中&#xff0c;数据以表的形式被逻辑地描述。 1.1 Row & Column 表由行和列组成: 行:表示用户数据的单行;列:用于描述一行数据中的…...

题目:求0—7所能组成的奇数个数。

题目&#xff1a;求0—7所能组成的奇数个数。 There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about being cheated should…...

网络协议学习笔记

HTTP协议 简单介绍 HTTP属于应用层 HTTP可以简单的理解成类似json一样的文本封装&#xff0c;但是这是超文本&#xff0c;所以可以封装的不止有文本&#xff0c;还有音视频、图片等 请求方法 HTTP报文格式 三大部分 起始行&#xff1a;描述请求或响应的基本信息头部字段…...

C语言文件操作:打开关闭,读写

程序文件 源程序文件&#xff08;后缀为.c&#xff09; 目标文件&#xff08;Windows环境后缀为.obj&#xff09; 可执行文件&#xff08;Windows环境后缀为.exe&#xff09; fputc FILE* pf fopen("test.txt","w");if (pf NULL){printf("%s\n"…...

启智CV机器人,ROS,ubuntu 20.04 【最后一步有问题】

资料&#xff1a; https://wiki.ros.org/kinetic/Installation/Ubuntu https://blog.csdn.net/qq_44339029/article/details/120579608 装VM。 装ubuntu20.04 desktop.iso系统。 装vm工具&#xff1a; sudo apt update sudo dpkg --configure -a sudo apt-get autoremove o…...

React-生成随机数和日期格式化

生成随机数 uuid文档&#xff1a;https://github.com/uuidjs/uuid npm install uuid import {v4 as uuidV4} from uuid 使用&#xff1a; uuidV4() 日期格式化 dayjs文档&#xff1a;安装 | Day.js中文网 npm install dayjs import dayjs from dayjs...

11Linux学习笔记

Linux 实操篇 目录 文章目录 Linux 实操篇1.rtm包&#xff08;软件&#xff09;1.1 基本命令1.2 基本格式1.3安装rtm包1.4卸载rtm包 2.apt包2.1 基本命令结构2.2 常用选项2.3常用命令 1.rtm包&#xff08;软件&#xff09; 1.1 基本命令 1.2 基本格式 1.3安装rtm包 1.4卸载r…...

004 仿muduo实现高性能服务器组件_Buffer模块与Socket模块的实现

​&#x1f308;个人主页&#xff1a;Fan_558 &#x1f525; 系列专栏&#xff1a;仿muduo &#x1f339;关注我&#x1f4aa;&#x1f3fb;带你学更多知识 文章目录 前言Buffer模块Socket模块 小结 前言 这章将会向你介绍仿muduo高性能服务器组件的buffer模块与socket模块的实…...

研发效能DevOps: Ubuntu 部署 JFrog 制品库

目录 一、实验 1.环境 2.Ubuntu 部署 JFrog 制品库 3.Ubuntu 部署 postgresql数据库 4.Ubuntu 部署 Xray 5. 使用JFrog 增删项目 二、问题 1.Ubuntu 如何通过apt方式部署 JFrog 制品库 2.Ubuntu 如何通过docker方式部署 JFrog 制品库 3.安装jdk报错 4.安装JFrog Ar…...