rust异步编程2

概述

*异步编程参考书籍: async-book
此学习根据Rust语言圣经 中tokio专栏,tokio 是一个将 rust提供的async/await 特性编写的异步代码运行起来的异步运行时. (tokio,async-std, smol等异步运行时框架)

  • 为什么要使用 异步运行时Tokio
    rust本身只提供异步编程时候所需要的基本特性,标准库中Future特性,这些特性单独使用没有多大用处,需要有一个运行时将这些特性实现代码运行起来 ,选择使用Tokio 基于Future,和MONO 两种系统的框架运行的

async/await 介绍

async作为rust异步编程的工具,async 将一个代码块转换成实现Future特征的状态机, 在转换成为Future后作用:在同步方法中调用阻塞函数(asyn转换函数)会阻塞整个线程,但是阻塞的Future会让出线程控制权,让其他Future 运行

  • 状态机器四要素: 状态,动作,事件,跳转。
    动作:打开 关不, 事件: 按按钮
    rust异步编程2_第1张图片
    在Tokio中 异步运行时候提供核心 一个reactor(订阅机制), 多个executor执行器
use futures::executor;
// 异步关键字
async fn hello(){
    println!("Hello!");
}

fn main() {
	// 执行器组塞式调用
    executor::block_on(hello());
    println!("Hello, world!");
}
-- 通过await方式调用 不阻塞方式调用
use futures::{self, executor};
use std::thread::sleep;
use std::time::Duration;

async fn learn_song() {
    sleep(Duration::from_secs(5));
    println!("learn song");
}

async fn sing_song() {
    println!("sing song");
}

async fn dance() {
    println!("dance");
}

// 先学会唱歌,唱歌 后在跳舞
async fn learn_and_sing_song() {
    learn_song().await;
    sing_song().await;
}

async fn async_main(){
    let f1 = learn_and_sing_song();
    let f2 = dance();
    futures::join!(f1, f2); // 使用 join 方法进行了阻塞
    
}

fn main() {
    executor::block_on(async_main());
    println!("Hello, world!");
}
sing song
dance
Hello, world!

经典:问题一:
本来根据async 的定义 当某一个Future线程被阻塞(睡眠)后应该让出线程控制权,让其他的线程运行 ,但rust代码中执行结果不对, 还是按照阻塞方式顺序执行 这是为什么???
executor::join!() 保证两个异步函数并行执行

 实际执行为什么会不符合预期结果
 主要原因在于 Sleep 函数, 在rust中使用Sleep函数后 认为你是将本线程进行休眠,不是进行阻塞,如果想要达到阻塞的情形, 使用 async-std, tokio 等运行时框架的 delay_for
 use futures;
use tokio::runtime::Runtime;
async fn learn_song() {
    // 是不是由于Sleep并没有让当前线程阻塞 只是 线程休眠 导致输出结果一样的 使用tokio
    //sleep(Duration::from_secs(5));
    //  for _ in 0..10000 {
    //
    //  }
    tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
    println!("learn song");
}

async fn sing_song() {
    println!("sing song");
}

async fn dance() {
    println!("dance");
}

// 先学会唱歌,唱歌 后在跳舞
async fn learn_and_sing_song() {
    learn_song().await; // 阻塞后续代码执行 await
    sing_song().await;
}

async fn async_main(){
    let f1 = learn_and_sing_song();
    let f2 = dance();
    futures::join!(f1, f2); // 使用 join 方法进行了阻塞

}

fn main() {
    let runtime = Runtime::new().unwrap();
    runtime.block_on(async_main());
    println!("Hello, world!");
}
H:/programe/rust/.cargo/bin/cargo.exe run --color=always --package async_move --bin async_move
    Finished dev [unoptimized + debuginfo] target(s) in 0.16s
     Running `target\debug\async_move.exe`
dance
learn song
sing song
Hello, world!

Process finished with exit code 0

在高并发编程中有两种方式 1. 采用多线程 2. async 异步编程(js , 只有一个线程,但是使用async 框架)
总之,async编程并没有比多线程更好,最终还是根据你的使用场景作出合适的选择,如果无需高并发,或者也不在意线程切换带来的性能损耗,那么多线程使用起来会简单、方便的多!最后再简单总结下:

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

你可能感兴趣的:(rust,开发语言,后端)