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

详解Rust异步编程

文章目录

    • 多线程编程与异步编程对比
    • 并发模型对比分析
    • 异步编程基础概念及用法

Rust的异步编程通过async/await语法和Future特性提供了一种高效的方式来处理并发任务,尤其在I/O密集型操作中表现出色。async/await异步编程模型性能高,还能支持底层编程,同时又像线程和协程那样无需过多的改变编程模型,但async模型的问题就是内部实现机制过于复杂,对于用户来说,理解和使用没有线程和协程简单。

多线程编程与异步编程对比

Rust的多线程编程和异步编程都是处理并发的常用方式,虽然它们都能够提高程序的并发性能,但它们在实现原理、使用场景、优缺点等方面存在一些重要差异。

1.概念区别
多线程编程
Rust的多线程编程利用操作系统的线程来并行执行任务,每个线程都有自己的执行上下文和栈。Rust通过std::thread模块来创建和管理线程。线程间的共享数据需要通过锁或原子操作来管理,以避免数据竞态。

异步编程
Rust的异步编程基于非阻塞I/O操作,并通过async/await语法实现。异步任务通常是在单线程中通过事件循环和任务调度来实现并发,而不是通过多个操作系统线程。Rust的异步编程主要依赖于Future和Tokio、async-std等库来管理和调度任务。

2.实现机制
多线程编程,每个线程都由操作系统调度,独立执行任务。线程通常会阻塞,直到执行完成,线程间的数据共享需要显式地通过Arc<Mutex>、RwLock或 Atomic等方式来进行同步。

异步函数是基于事件循环和任务调度器的,执行时不会阻塞线程,而是通过协作式多任务调度实现并发。当遇到需要等待的操作(如 I/O、网络请求等)时,异步任务会主动让出控制权,直到操作完成才会继续执行。异步编程依赖于Future和.await来控制任务的调度和执行。

3.使用场景
多线程编程适用于计算密集型任务,如大规模数据处理、图像处理、视频渲染等。当任务需要大量CPU资源并且任务之间的执行是独立的时,使用多线程能够显著提升性能。适合任务需要真实并行执行的场景,比如将任务分配到多个CPU核心上运行。

异步编程适用于I/O密集型任务,如网络请求、文件操作、数据库访问等。当任务的瓶颈在于等待外部资源时,异步编程能够显著提升效率。用于高并发的Web服务器、网络客户端等应用,特别是当大量连接/请求需要同时处理时,异步编程的优势非常明显。

有大量IO任务需要并发运行时,选async模型
有部分IO任务需要并发运行时,选多线程,如果想要降低线程创建和销毁的开销,可以使用线程池
有大量CPU密集任务需要并行运行时,例如并行计算,选多线程模型,且让线程数等于或者稍大于CPU核心数
无所谓时统一选多线程

4.优缺点对比

种类优点缺点
多线程编程1.真正的并行执行,适合CPU密集型任务
2.线程间独立,控制直观,易于理解;
3.无数据竞争和内存问题是安全的
1.创建和销毁线程的成本较高,过多线程可能导致上下文切换的开销。
2.线程间同步需要额外处理,增加了复杂性。
3.线程调度由操作系统管理,不能完全控制线程执行顺序。
异步编程1.适合I/O密集型任务,能在单线程上处理大量并发任务,避免了线程创建和上下文切换的开销。
2.异步编程通过事件循环调度,不需要操作系统线程支持,因此能在较低的系统资源下运行。
3.通过async/await语法,代码更简洁、易于理解
1.无法有效利用CPU,不适合CPU密集型任务。
2.异步代码可能会引入潜在的生命周期和借用问题。
3.异步编程对调度器和运行时(如 Tokio 或 async-std)有一定依赖,这可能增加外部库的复杂性

5.性能对比
多线程每个线程都是由操作系统调度的,具有独立的栈和上下文,因此能够实现真正的并行。在多核CPU上适合处理计算密集型任务。然而线程创建和销毁的开销相对较大。
异步操作在单线程中,通过任务调度来处理并发,可以避免线程的创建和销毁开销。适合I/O密集型任务,但对CPU密集型任务的性能提升有限,可能需要结合多线程或多进程来解决。

async和多线程的性能对比

操作async线程
创建0.3 微秒17 微秒
线程切换0.2 微秒1.7 微秒

并发模型对比分析

对比分析各种并发模型的优缺点及适用场景。

并发模型优点缺点适用场景
OS 线程简单直接,原生支持,易于理解,不需要改变编程模型上下文切换损耗大,线程间同步困难,性能对 I/O 密集型场景不理想适合 CPU 密集型任务、并行计算
事件驱动性能高,处理并发时非常高效回调地狱,非线性控制流导致数据流向和错误传播难以控制,降低可维护性适合 I/O 密集型任务,尤其是网络服务等
协程支持大量并发任务,性能高,易于实现并发编程抽象层次过高,无法触及底层细节,系统编程和自定义异步运行时难用适合需要大量并发任务的场景,但不涉及底层系统编程
Actor 模型贴近现实,易于实现并发计算,消息传递模式适合分布式系统设计流控制、失败重试等复杂场景下不太好用适合分布式系统、松耦合的并发计算场景
async/await高效性能,支持底层编程,同时具备线程和协程的特点,无需改变编程模型实现复杂,理解和使用有一定难度,但已有封装适合高并发、异步 I/O 的场景,尤其是需要精细控制并发行为时

async是Rust选择的异步编程模型

异步编程基础概念及用法

1.async函数与await
通过将函数标记为async。Rust会将其转换为返回Future类型的函数。Future是Rust中表示异步操作的核心类型,表示一个尚未完成但可能会在将来完成的计算。
await用于挂起当前任务,直到一个Future完成并返回结果。调用await时当前任务会被暂停,直到Future完成并返回结果。await并不会阻塞当前的线程,而是异步的等待Future的完成。

有两种方式可以使用async: async fn用于声明函数,async { … }用于声明语句块,它们会返回一个实现Future特征的值.

//该函数返回一个Future<i32>  
async fn foo() -> i32 {42
}
fn bar() -> impl Future<Output = u8> {// 下面的async语句块返回Future<Output = u8>  async {let x: u8 = foo().await;x + 5}
}async fn bar() {//block_on会阻塞当前线程  //let future = foo();//block_on(future); //与block_on不同.await并不会阻塞当前的线程let result = foo().await;println!("Result: {}", result);
}

2.Future类型
在Rust中异步操作通过Future类型表示,Future本身定义了一个状态机,它跟踪操作的进度。一个Future可以处于以下状态:

  • Pending: 操作正在进行中,尚未完成。
  • Ready: 操作已完成,具有结果值。

Future是惰性执行的,意味着它不会在创建时立即运行,而是在调用await或通过poll方法驱动执行时才开始执行

3.async/await的工作机制
async函数在编译时被转换为一个状态机。编译器会为每个await操作生成一个状态转换的过程,这样可以有效地管理执行流程而不阻塞线程,await操作会挂起函数,直到被等待的Future完成。这个过程并不会阻塞当前线程,而是通过poll的方式让任务调度器在适当时机恢复任务。

4.异步执行模型与任务调度
Rust本身并不提供内置的异步运行时,它依赖于外部库(例如Tokio和async-std)来提供任务调度和执行。常见的异步执行模型如下:
单线程模型: 许多异步框架使用一个单线程执行所有异步任务的调度器。在这个模型中,调度器在后台执行多个任务,尽量避免阻塞增加效率。
多线程模型: 某些框架(如Tokio)支持多线程模型,其中多个线程可以同时运行异步任务。

Tokio调用方法

# Cargo.toml
# 配置依赖库  
[dependencies]
tokio = { version = "1", features = ["full"] }
//使用Tokio运行时
use tokio::time::{sleep, Duration};async fn hello_world() {println!("Hello");sleep(Duration::from_secs(1)).await;println!("World");
}#[tokio::main]
async fn main() {hello_world().await;
}

5.异步错误处理
Rust的异步错误处理与同步代码相似,使用Result和Option类型。异步函数通常会返回Result类型。

async fn might_fail() -> Result<(), String> {// Some async operation that might failErr("Something went wrong".to_string())
}#[tokio::main]
async fn main() {match might_fail().await {Ok(_) => println!("Success"),Err(e) => println!("Error: {}", e),}
}

6.并发与并行
Rust的异步模型能够在单线程中并发执行多个异步任务,这意味着即使你只有一个线程,异步任务依然可以并发执行,但它们实际上是通过时间片轮转来实现的。
如果需要并行(例如在多个CPU核心上运行任务),你可以使用多线程运行时(如Tokio或async-std)。

use tokio::task;async fn task1() {println!("Task 1 started");// simulate async worktokio::time::sleep(tokio::time::Duration::from_secs(1)).await;println!("Task 1 done");
}async fn task2() {println!("Task 2 started");// simulate async worktokio::time::sleep(tokio::time::Duration::from_secs(1)).await;println!("Task 2 done");
}#[tokio::main]
async fn main() {let t1 = task::spawn(task1());let t2 = task::spawn(task2());let _ = tokio::try_join!(t1, t2); // Wait for both tasks to complete
}

7.异步流与通道
Rust还提供了异步流(Stream)和通道(Channel)来处理更复杂的异步场景,例如处理一系列异步数据流或者在不同任务之间传递消息。
异步流(Stream): 表示一系列异步值的集合,可以通过Stream提供的next()方法来异步地获取这些值。
通道(Channel): 异步通道允许不同任务之间传递数据。常用的通道库包括tokio::sync::mpsc和async-std::channel。

Stream类似于Future但是它可以生成多个值,直到它完成。它的行为与标准库中的Iterator很像。Stream trait定义了poll_next 方法,用于返回流中的下一个元素,返回值为Poll<Option>。

  • Poll::Pending: 表示流还没有数据。
  • Poll::Ready(Some(item)): 表示流有数据。
  • Poll::Ready(None): 表示流已完成,没有更多数据。
async fn send_recv() {const BUFFER_SIZE: usize = 10;let (mut tx, mut rx) = mpsc::channel::<i32>(BUFFER_SIZE);tx.send(1).await.unwrap();tx.send(2).await.unwrap();drop(tx);assert_eq!(Some(1), rx.next().await);assert_eq!(Some(2), rx.next().await);assert_eq!(None, rx.next().await);
}

8.性能分析
Rust的异步编程具有高效性,特别是在处理I/O密集型任务时。由于Rust的所有权系统和无垃圾回收机制,异步任务的内存管理得到了很好的保证,这使得Rust异步代码非常高效。

  • 无堆分配的异步任务: Rust提供了Pin和Box等类型来确保异步任务的内存位置不会发生变化,避免了运行时的额外开销。
  • 零成本抽象: Rust的异步编程模型通过编译时优化,提供了与同步代码几乎相同的性能,而不会引入额外的运行时开销。

9.同时运行多个Future

//两个future 一个先运行 另一个后运行  
async fn enjoy_book_and_music() -> (Book, Music) {let book = enjoy_book().await;let music = enjoy_music().await;(book, music)
}//发运行两个 Future
//如果希望同时运行一个数组里的多个异步任务,可以使用 futures::future::join_all 方法  
use futures::join;
async fn enjoy_book_and_music() -> (Book, Music) {let book_fut = enjoy_book();let music_fut = enjoy_music();join!(book_fut, music_fut)
}//希望在某一个Future报错后就立即停止所有Future的执行,可以使用 try_join!  
//有一点需要注意传给try_join!的所有Future都必须拥有相同的错误类型。
//如果错误类型不同,可以考虑使用来自 futures::future::TryFutureExt 模块的 map_err 和 err_info 方法将错误进行转换  
use futures::try_join;
async fn get_book() -> Result<Book, String> { /* ... */ Ok(Book) }
async fn get_music() -> Result<Music, String> { /* ... */ Ok(Music) }async fn get_book_and_music() -> Result<(Book, Music), String> {let book_fut = get_book();let music_fut = get_music();try_join!(book_fut, music_fut)
}

10.async函数的生命周期问题
当异步函数接受引用类型的参数时Future的生命周期必须至少与参数的生命周期相同。否则编译器会报错。
解决方法:通过将引用传入async语句块内,使其生命周期延续到Future返回时,避免生命周期不匹配的问题。

async move会捕获外部变量并将其所有权转移到异步任务中。这解决了借用生命周期的问题,避免了变量在任务完成前被释放。
使用async move时,所有的捕获变量的所有权会被转移,且该变量不再受到生命周期的限制,无法与其他代码共享。

// 多个不同的async语句块可以访问同一个本地变量 只要它们在该变量的作用域内执行
async fn blocks() {let my_string = "foo".to_string();let future_one = async {// ...println!("{my_string}");};let future_two = async {// ...println!("{my_string}");};// 运行两个 Future 直到完成let ((), ()) = futures::join!(future_one, future_two);
}//由于async move会捕获环境中的变量,因此只有一个async move语句块可以访问该变量
//有非常明显的好处: 变量可以转移到返回的 Future 中,不再受借用生命周期的限制
fn move_block() -> impl Future<Output = ()> {let my_string = "foo".to_string();async move {// ...println!("{my_string}");}
}

相关文章:

详解Rust异步编程

文章目录 多线程编程与异步编程对比并发模型对比分析异步编程基础概念及用法 Rust的异步编程通过async/await语法和Future特性提供了一种高效的方式来处理并发任务&#xff0c;尤其在I/O密集型操作中表现出色。async/await异步编程模型性能高&#xff0c;还能支持底层编程&…...

Vue + Element UI 实战技巧:如何实现 el-table 重新加载数据后折叠所有展开行

在 Vue 中使用 Element UI 的 el-table 组件时&#xff0c;如果你想要在数据重新加载后折叠所有行的展开状态&#xff0c;你可以通过维护一个数据属性来追踪哪些行是展开的&#xff0c;并在数据更新时重置这个属性。 以下是一个简单的示例来说明如何实现这个功能&#xff1a; …...

linux静态链接和动态链接

静态链接的特点 程序独立性高 静态链接是在程序编译时&#xff0c;将所有需要的目标文件以及它们所依赖的库文件中的代码和数据链接成一个可执行文件。一旦链接完成&#xff0c;这个可执行文件就包含了运行所需的全部内容&#xff0c;不依赖外部的库文件。例如&#xff0c;一个…...

计算机网络学习资料全攻略

计算机网络是计算机科学中一个非常重要的分支&#xff0c;它涉及到数据在计算机系统之间的传输和通信。随着互联网的快速发展&#xff0c;对计算机网络知识的掌握变得越来越重要。本文将为您提供一份全面的计算机网络学习资料指南&#xff0c;帮助您从基础到高级逐步深入学习。…...

第七课 Unity编辑器创建的资源优化_UI篇(UGUI)

上期我们学习了简单的Scene优化&#xff0c;接下来我们继续编辑器创建资源的UGUI优化 UI篇&#xff08;UGUI&#xff09; 优化UGUI应从哪些方面入手&#xff1f; 可以从CPU和GPU两方面考虑&#xff0c;CPU方面&#xff0c;避免触发或减少Canvas的Rebuild和Rebatch&#xff0c…...

Go的简单问题问答

基础问题回答 Go 的主要特点是什么&#xff1f; 简洁&#xff1a;语法简化&#xff0c;减少复杂性。并发&#xff1a;内置 Goroutine 和 Channel&#xff0c;支持轻量级并发。静态类型&#xff1a;强类型语言&#xff0c;编译时检查错误。跨平台&#xff1a;编译生成独立的二进…...

SVN迁移至Git,保留commit提交记录

SVN迁移至Git 如何将 SVN 仓库迁移到 Git 并保留提交记录一、生成userinfo.txt二. 使用 git svn clone 命令迁移 SVN 到 Git2.1. 基本命令格式2.2. 示例&#xff1a;从 SVN 克隆到 Git参数说明&#xff1a;2.3 执行的过程遇到的窗口2.4. 迁移过程 三. 将 Git 仓库推送到远程 Gi…...

一站式指导:在Neo4j与PostgreSQL间实现高效数据同步

作者&#xff1a;后端小肥肠 &#x1f347; 我写过的文章中的相关代码放到了gitee&#xff0c;地址&#xff1a;xfc-fdw-cloud: 公共解决方案 &#x1f34a; 有疑问可私信或评论区联系我。 &#x1f951; 创作不易未经允许严禁转载。 姊妹篇&#xff1a; 数据同步的艺术&#…...

linux-安全-iptables防火墙基础笔记

目录 一、 iptables链结构 五链 二、 iptables表结构 四表 三、 匹配流程 四、 语法 五、 匹配 1. 通用匹配 2. 隐含匹配 3. 显示匹配 六、 SNAT 七、 DNAT 八、 规则备份及还原 1. 备份 2. 还原 这篇将讲解iptables防火墙的基础知识 一、 iptables链结构 规则…...

Redis——主从复制原理

Redis的主从复制原理是其高可用性和分布式读取能力的重要基础。以下是Redis主从复制原理的详细解释&#xff1a; 一、主从复制的基本概念 Redis的主从复制是一种数据复制和备份的方式&#xff0c;它允许一个主节点&#xff08;Master&#xff09;将其所有的数据同步到一个或多…...

vue2 虚拟DOM 和 真实DOM (概念、作用、Diff 算法)

虚拟 DOM 和 真实DOM&#xff08;概念、作用、Diff 算法&#xff09; 1.1 概念 真实 DOM&#xff08;Document Object Model&#xff09;&#xff1a;是浏览器中用于表示文档结构的树形结构。 <h2>你好</h2>虚拟DOM&#xff1a;用 JavaScript 对象来模拟真实 DOM…...

王道考研编程题总结

我还在完善中&#xff0c;边复习边完善&#xff08;这个只是根据我自身总结的&#xff09; 一、 线性表 1. 结构体 #define MaxSize 40 typedef struct{ElemType data[MaxSize]&#xff1b;int length; }SqList 2. 编程题 1. 删除最小值 题意 &#xff1a;从顺序表中删除…...

手机租赁系统开发全攻略 创新服务助力企业智能转型

内容概要 在当今数字化飞速发展的时代&#xff0c;“手机租赁系统开发”正逐渐成为企业智能转型的必然选择。这一过程并不简单&#xff0c;但关键流程的解析将帮助企业理清思路。首先&#xff0c;了解需求和目标是基础&#xff0c;之后制定详细计划和流程图&#xff0c;让整件…...

git回退到某个版本git checkout和git reset命令的区别

文章目录 1. git checkout <commit>2. git reset --hard <commit>两者的区别总结推荐使用场景* 在使用 Git 回退到某个版本时&#xff0c; git checkout <commit> 和 git reset --hard <commit> 是两种常见的方式&#xff0c;但它们的用途和影响有很…...

如何使用Spring Boot进行Web开发?

Spring Boot 是一个基于 Java 的框架&#xff0c;它简化了新 Spring 应用的初始设置和开发过程。使用 Spring Boot 进行 Web 开发可以让你快速创建独立的、生产级别的基于 Spring 的应用。下面是使用 Spring Boot 进行 Web 开发的基本步骤&#xff1a; 文章目录 1. 环境准备2. …...

error=‘null‘], commandType=io.lettuce.core.RedisPublisher$SubscriptionCommand]

问题 查看java应用启动日志输出下面错误&#xff1a; errornull], commandTypeio.lettuce.core.RedisPublisher$SubscriptionCommand] Completing command LatencyMeteredCommand [typeINFO, outputStatusOutput [output# Server redis_version:4.0.14 redis_git_sha1:000…...

AI PC处理器ARM架构-引入NPU和大模型

AI PC处理器架构变化&#xff1a;ARM低功耗、引入NPU和大模型 AI进化加速端侧落地&#xff0c;新一轮浪潮蓄势待发(2024)”。ARM(Advanced RISC Machine)架构和x86架构是两种主要的处理器架构&#xff0c;它们在设计理念、应用场景和性能特点等方面有显著的差异。 ARM架构是一…...

python之opencv库Haar级联分类器检测人脸--‘haarcascade_frontalface_default.xml‘

python之opencv库Haar级联分类器检测人脸–‘haarcascade_frontalface_default.xml’ opencv库&#xff1a; 它由 Intel 公司发起并参与开发&#xff0c;其初衷是为了提供高效的计算机视觉算法实现。随着计算机视觉领域的发展&#xff0c;OpenCV不断更新和完善&#xff0c;吸引…...

「Mac畅玩鸿蒙与硬件37」UI互动应用篇14 - 随机颜色变化器

本篇将带你实现一个随机颜色变化器应用。用户点击“随机颜色”按钮后&#xff0c;界面背景会随机变化为淡色系颜色&#xff0c;同时显示当前的颜色代码&#xff0c;页面还会展示一只猫咪图片作为装饰&#xff0c;提升趣味性。 关键词 UI互动应用随机颜色生成状态管理用户交互…...

确定 POST 请求中的数据字段

在使用 requests 进行 HTTP 请求时&#xff0c;data 和 params 是两种常见的参数&#xff0c;用于传递不同类型的数据。以下是它们的作用和区别&#xff1a; 1. data 的作用 用于 POST 请求的主体。通常传递表单数据或 JSON 数据。在 HTTP 请求中&#xff0c;data 中的内容会…...

Linux - DNS服务器

六、DNS服务器 1、简介 DNS&#xff08;Domain Name System&#xff09;是互联网上的一项服务&#xff0c;它作为将域名和IP地址相互映射的一个分布式 数据库&#xff0c;能够使人更方便的访问互联网。 DNS系统使用的是网络的查询&#xff0c;那么自然需要有监听的port。DNS使…...

探究 SpringBoot 结合 MVC 高校办公室行政事务管理系统的设计与应用实现

摘 要 身处网络时代&#xff0c;随着网络系统体系发展的不断成熟和完善&#xff0c;人们的生活也随之发生了很大的变化&#xff0c;人们在追求较高物质生活的同时&#xff0c;也在想着如何使自身的精神内涵得到提升&#xff0c;而读书就是人们获得精神享受非常重要的途径。为了…...

蓝桥杯-扫雷

这题不难&#xff0c;就是麻烦一点&#xff0c;这里暴力求解了直接 题目链接&#xff1a; 扫雷 AC代码&#xff1a; import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scanner scan ne…...

Hive高可用配置

在hive的商用上没有集群一说&#xff0c;而且它本身也不是数据库&#xff0c;只是hadoop的数据sql化工具&#xff0c;但是hive可以配置高可用&#xff0c;通常业内对元数据服务会开5个&#xff0c;而HS2服务开3个&#xff0c;来保证hive服务的高可用 配置方式也很简单&#xf…...

探索AI新世界!热门工具与学习资源免费获取

​抖知书老师推荐&#xff1a; 人工智能技术的迅速发展让人们既充满期待又有些迷茫。有人担忧被AI技术取代&#xff0c;有人却积极拥抱这场科技浪潮。无论你处于哪种心态&#xff0c;人工智能已经深入到我们生活的方方面面。如果你希望轻松掌握最新的AI工具与动态&#xff0c;…...

MAUI APP开发蓝牙协议的经验分享:与跳绳设备对接

在开发MAUI应用程序时&#xff0c;蓝牙协议的应用是一个重要的环节&#xff0c;尤其是在需要与外部设备如智能跳绳进行数据交换的场景中。以下是我在开发过程中的一些经验和心得&#xff0c;希望能为你的项目提供帮助。 1. 蓝牙协议基础 蓝牙协议是无线通信的一种标准&#x…...

常见Linux命令(详解)

文章目录 常见Linux命令文件目录类命令pwd 打印当前目录的绝对路径ls 列出目录内容cd 切换路径mkdir 建立目录rmdir 删除目录touch 创建空文件cp 复制文件或目录rm 移除文件或者目录mv 移动文件与目录或重命名cat 查看文件内容more 文件分屏查看器less 分屏显示文件内容head 显…...

LeetCode763. 划分字母区间(2024冬季每日一题 23)

给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段&#xff0c;同一字母最多出现在一个片段中。 注意&#xff0c;划分结果需要满足&#xff1a;将所有划分结果按顺序连接&#xff0c;得到的字符串仍然是 s 。 返回一个表示每个字符串片段的长度的列表。 示例 1&a…...

【k8s 深入学习之 event 聚合】event count累记聚合(采用 Patch),Message 聚合形成聚合 event(采用Create)

参考 15.深入k8s:Event事件处理及其源码分析 - luozhiyun - 博客园event 模块总览 EventRecorder:是事件生成者,k8s组件通过调用它的方法来生成事件;EventBroadcaster:事件广播器,负责消费EventRecorder产生的事件,然后分发给broadcasterWatcher;broadcasterWatcher:用…...

Java--数组的定义与使用

1.数组的基本概念 1.1为什么用数组 在程序设计中,每一个数据总是对应一个变量.当数据量越大,就需要更多的变量来存储.我们将相同类型的数据存储到一个集合中,就可以更方便我们对数据进行访问,同时可以减少不断定义变量.这个集合就叫做数组 1.2数组的定义 数组是一种基本的数…...

tcpdump抓包wireshark分析

背景 分析特定协议的数据包&#xff0c;如 HTTP、DNS、TCP、UDP 等&#xff0c;诊断网络问题&#xff0c;例如连接故障、延迟和数据包丢失。 大概过程 1.安装tcpdump yum update yum install tcpdump2.抓包&#xff0c;从当前时间起&#xff0c;一小时后停止&#xff0c…...

qtcanpool 知 09:测试框架

文章目录 前言不满改进优化后语 前言 很久以前&#xff0c;作者写的代码都没有测试用例&#xff0c;最多就是写个 demo 验证一下&#xff0c;毕竟不是专业出身&#xff0c;也没经过大公司的洗礼。 后来&#xff0c;参与到一些项目才知道有专门的测试&#xff0c;而且开发也要测…...

使用Apache HttpClient发起一个GET HTTP请求

Apache HttpClient 是一个强大且灵活的Java库&#xff0c;用于处理HTTP请求。 它提供了广泛的功能&#xff0c;包括对不同HTTP方法的支持、连接管理、Cookie处理等。 无论是与RESTful API交互、下载网页内容还是自动化网页任务&#xff0c;Apache HttpClient 都能通过其简洁而…...

C++ STL 容器系列(三)list —— 编程世界的万能胶,数据结构中的百变精灵

STL系列学习参考&#xff1a; C STL系列__zwy的博客-CSDN博客https://blog.csdn.net/bite_zwy/category_12838593.html 学习C STL的三个境界&#xff0c;会用&#xff0c;明理&#xff0c;能扩展&#xff0c;STL中的所有容器都遵循这个规律&#xff0c;下面我们就按照这三个境…...

【前端学习笔记】TypeScript学习

1.什么是TypeScript TypeScript&#xff08;简称 TS&#xff09;是微软公司开发的一种基于 JavaScript &#xff08;简称 JS&#xff09;语言的编程语言。TypeScript 可以看成是 JavaScript 的超集&#xff08;superset&#xff09;&#xff0c;添加了类型系统和编译时类型检查…...

qt三大调试方法总结(printf\qDebug\qCDebug)

文章目录 1 传统方法2 qDebug传统方法扩展1 控制输出扩展2 日志格式扩展3 日志保存扩展4 源码定义护展5 开源扩展3 qCDebug方法扩展1 控制扩展2 格式化扩展3 保存日志扩展4 源码定义参考1 传统方法 #include<stdio.h> printf(“xboard hello printf”) 2 qDebug传统方法…...

耶鲁大学公开课《心理学导论》学习笔记:第 1 课 - 导论

概述 作为一个程序员&#xff0c;或者说&#xff0c;我们不管做什么行业&#xff0c;都可以或多或少的学习一些心理学 我们在生活工作中&#xff0c;其实都会有意无意的接触一些心理学原理&#xff0c;例如&#xff0c;【番茄工作法】、【内在动机与外在激励】 这里选择的是&…...

Android ConstraintLayout 约束布局的使用手册

目录 前言 一、ConstraintLayout基本介绍 二、ConstraintLayout使用步骤 1、引入库 2、基本使用&#xff0c;实现按钮居中。相对于父布局的约束。 3、A Button 居中展示&#xff0c;B Button展示在A Button正下方&#xff08;距离A 46dp&#xff09;。相对于兄弟控件的约束…...

STM32F030单片机AD采集应用总结

最近在设计一款产品的AD时&#xff0c;采集到的电压老是比输入电压0.2V左右&#xff0c;电路如图所示 查阅资料得知&#xff0c;STM32f030 的输入阻抗应小于 50K。于是将电阻改为 39K/10K&#xff0c;但情况依旧。随后&#xff0c;干脆将电阻值改为 3.9K/1K&#xff0c;虽有一定…...

Web开发基础学习——通过React示例学习模态对话框

Web开发基础学习系列文章目录 第一章 基础知识学习之通过React组件学习模态对话框 文章目录 Web开发基础学习系列文章目录前言一、创建新的 React 应用二、 创建模态对话框组件三、修改 App.js四、 添加样式五、启动应用六、访问应用总结 前言 模态对话框&#xff08;Modal D…...

实例分割详解

实例分割详解 引言 实例分割是计算机视觉领域的一项复杂任务&#xff0c;它要求模型能够识别图像中不同类别的对象&#xff0c;并对每个单独的对象进行像素级别的分类。与语义分割不同的是&#xff0c;实例分割不仅要区分不同的类别&#xff0c;还要识别同一类别中的不同个体…...

Flink四大基石之State(状态) 的使用详解

目录 一、有状态计算与无状态计算 &#xff08;一&#xff09;概念差异 &#xff08;二&#xff09;应用场景 二、有状态计算中的状态分类 &#xff08;一&#xff09;托管状态&#xff08;Managed State&#xff09;与原生状态&#xff08;Raw State&#xff09; 两者的…...

vue深入理解输入框字符限制的优化设计

文章目录 深入理解输入框字符限制的优化设计背景与挑战输入框限制的重要性常见需求 多种实现方法解析方法一&#xff1a;基于实时过滤的字符限制方法二&#xff1a;借助正则验证方法三&#xff1a;提交时二次校验 性能优化无障碍设计延伸场景与最佳实践1. 多语言国际化支持2. 动…...

MySQL的子查询

SQL语句中嵌套select语句,嵌套查询 案例&#xff1a; select * from t1 where column1 (select column1 from t2); 补&#xff1a; 1.子查询外部的语句可以是insert/update/delete/select的任何一个 2.位置也可以在where/from/select之后 类型&#xff1a; 1.标量子查询…...

Kubernetes架构原则和对象设计

云原生学习路线导航页&#xff08;持续更新中&#xff09; 快捷链接 Kubernetes常见问题解答 本文从 Google Borg系统的架构设计开始&#xff0c;深入讲解Kubernetes架构及组件的基本原理 1.什么是云计算 1.1.传统行业应用 假设有10台服务器&#xff0c;两个应用。小规模管…...

npm : 无法加载文件 D:\nodejs\npm.ps1,因为在此系统上禁止运行脚本

要以管理员身份打开PowerShell&#xff0c;请按照以下步骤操作&#xff1a; 在Windows搜索框中查找PowerShell&#xff1a; 在任务栏上&#xff0c;点击左下角的Windows徽标&#xff08;或按Win S键&#xff09;以打开搜索框。输入“PowerShell”以查找PowerShell应用程序。右…...

Linux CentOS

​阿里云开源镜像下载链接 https://mirrors.aliyun.com/centos/7/isos/x86_64/ VMware 安装 CentOS7 自定义 下一步 选择稍后安装操作系统 选择 输入 查看物理机CPU内核数量 CtrlShiftEsc 总数不超过物理机内核数量 推荐内存 自选 推荐 推荐 默认 拆分成多个 默认 自定义硬件…...

如何用注册机破解Reflexive游戏

相信有许多小朋友&#xff08;像我以前一样&#xff09;已经迫不及待地准备准备对浩瀚的、像三星堆一般的Reflexive游戏合集进行考古挖掘工作了。不巧的是&#xff0c;打开游戏之后发现常常提示要付费才能解锁完整版。 一、下载注册机与破解文件 首先&#xff0c;在我的永硕网…...

【算法day7】字符串:反转与替换

题目引用 反转字符串反转字符串II替换数字 1.反转字符串 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间&#xff0c;你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 示例 1&am…...

基于Linux C++多线程服务器 + Qt上位机开发 + STM32 + 8266WIFI的智慧无人超市

前言 针对传统超市购物车结账排队时间长、付款效率低的问题&#xff0c;提出了一种更符合现代社会人们购物方式-基于RFID的自助收银系统。习惯了快节奏生活的人们都会选择自助收银机结账&#xff0c;理由显而易见&#xff1a;自助收银机结账很方便&#xff0c;几乎不用排队&am…...