Rust tokio使用

一、库引入

为了学习tokio库的全部特性,cargo.toml的配置如下:

tokio = { version = "0.3", features = ["full"] }

二、Task使用示例

1.最简单的示例,验证tokio库导入成功,并能够成功运行。

async fn main() {
    println!("Hello, world!");
}

2.tokio任务阻塞+await示例

use tokio::time::Duration;
 
#[tokio::main] //此处引入tokio 宏/macro
async fn main() {
    //主线程
    tokio::task::spawn_blocking(|| {
        //运行在一个阻塞的线程,可以看作是一个比较耗时的操作
        sleep(Duration::from_millis(10000));
        println!("hi");
    }).await.unwrap();//使用await关键字等待阻塞线程的任务完成
    //要等待阻塞线程完成后,主线程才能执行
    println!("hello");
}

这个示例执行的结果是,等待10s后先输出hi,后输出hello。

3.tokio任务阻塞示例

use tokio::time::Duration;
 
#[tokio::main] //此处引入tokio 宏/macro
async fn main() {
    //主线程
    tokio::task::spawn_blocking(|| {
        //运行在一个阻塞的线程,可以看作是一个比较耗时的操作
        sleep(Duration::from_millis(10000));
        println!("hi");
    });//此处未使用await关键字等待阻塞线程的任务完成
    //无需等待阻塞线程完成,主线程直接执行
    println!("hello");
}

这个示例执行的结果是,先输出hello,然后等待10s输出hi

4.tokio任务不阻塞+await示例

use tokio::time::Duration;
 
#[tokio::main] //此处引入tokio 宏/macro
async fn main() {
    //主线程
    //tokio::task::spawn等价于thread::spawn的异步使用
    tokio::task::spawn(async{
        //运行在一个不阻塞的线程
        sleep(Duration::from_millis(10000));
        println!("hi");
    }).await.unwrap();//使用await关键字等待阻塞线程的任务完成
     //要等待线程完成后,主线程才能执行
    println!("hello");
}

这个示例执行的结果是,等待10s后先输出hi,后输出hello。

5.tokio任务不阻塞示例

use tokio::time::Duration;
 
#[tokio::main] //此处引入tokio 宏/macro
async fn main() {
    //主线程
    //tokio::task::spawn等价于thread::spawn的异步使用
    tokio::task::spawn(async{
        //运行在一个不阻塞的线程
        sleep(Duration::from_millis(10000));
        println!("hi");
    });//此处未使用await关键字等待阻塞线程的任务完成
    //无需等待阻塞线程完成,主线程直接执行
    println!("hello");
}

这个示例执行的结果是,先输出hello,然后等待10s输出hi

6.tokio多任务不阻塞示例

 
#[tokio::main] //此处引入tokio 宏/macro
async fn main() {
    tokio::task::spawn(async {//任务先抢占到线程就先输出hi1,操作耗时多,最后输出
        println!("hi1");
    });
    tokio::task::spawn(async {//任务先抢占到线程就先输出hi2,操作耗时多,最后输出
        println!("hi2");
    });
    println!("hello");
}

这个示例执行的结果是,先输出hello,后输出hi1和hi2,hi1和h2的出现顺序是不确定的。

7.tokio多任务不阻塞+单await示例

async fn main() {
    tokio::task::spawn(async {
        println!("hi1");//一定最先输出
    }).await;
    tokio::task::spawn(async {
        println!("hi2");//任务所属线程可能抢占不到执行所需的资源,主线程直接退出
    });
    println!("hello");//切到主线程,第二输出
}

这个示例执行的结果是,先等待h1输出,而后输出hello,最后输出hi2,也可能不输出hi2.

async fn main() {
    tokio::task::spawn(async {
        println!("hi1");//任务所属线程优先级较高,可以抢占到执行所需的资源
    });
    tokio::task::spawn(async {
        println!("hi2");//一定会执行,使用await会等待任务所属线程先完成,然后执行后续的操作
    }).await;
    println!("hello");//主线程最后执行
}

这个示例执行的结果是,可能先输出hi2,再输出hi1,最后输出hello,也可能是先输出hi1,再输出hi2,最后输出hello(这种可能性高)

8.tokio多任务阻塞示例

async fn main() {
    tokio::task::spawn_blocking(|| {
        //运行在一个阻塞的线程中
        println!("hi1");//分配到专属线程池执行
    });
    tokio::task::spawn_blocking(|| {
        //运行在一个阻塞的线程中
        println!("hi2");//分配到专属线程池执行
    });
    println!("hello");//因为任务处于阻塞,主线程最先输出
}

这个示例执行的结果是,先输出hello,再输出hi1和hi2,h1和h2输出顺序不定,为什么主线程在输出后不直接退出?因为还有任务处于阻塞没有返回,只有阻塞的任务完成,程序才会退出。

9.tokio多任务阻塞+单await示例

async fn main() {
    tokio::task::spawn_blocking(|| {
        println!("hi1");//使用await关键字,主线程需要等待任务执行完成才能执行
    }).await;
    tokio::task::spawn_blocking(|| {
        println!("hi2");//处于阻塞线程,等待主线程执行完,再执行
    });
    println!("hello");
}

这个示例执行的结果是,先输出hi1,然后输出hello,最后输出hi2

async fn main() {
    tokio::task::spawn_blocking(|| {
        println!("hi1");//操作不耗时,直接执行,不能超过await执行的时间,超过最后执行
    });
    tokio::task::spawn_blocking(|| {
        println!("hi2");//使用await关键字,主线程需要等待任务执行完成才能执行
    }).await;
    println!("hello");
}

这个示例执行的结果是,先输出hi1,然后输出hi2,最后输出hello

10.单线程环境下任务阻塞和任务不阻塞示例

use std::thread::sleep;
use tokio::time::Duration;
 
fn main() {
    //构造单线程tokio运行环境
    let runtime = Builder::new_multi_thread().
        max_threads(1).
        enable_all().
        build().
        expect("create tokio runtime failed");
    runtime.spawn(async {//相当于tokio::task::spawn
        //处于单线程中
        println!("hi1");
    });
    runtime.spawn(async {//相当于tokio::task::spawn
        println!("hi2");//处于单线程中
    });
    println!("hello");
}

这个示例执行的结果是,先输出hello,再输出hi1,再输出hi2,这个输出顺序是确定的,和示例6有所区别

use std::thread::sleep;
use tokio::time::Duration;
 
fn main() {
    //构造单线程tokio运行环境
    let runtime = Builder::new_multi_thread().
        max_threads(1).
        enable_all().
        build().
        expect("create tokio runtime failed");
    runtime.spawn(async {//相当于tokio::task::spawn
        //处于单线程中,执行了耗时的操作,影响了其他任务的执行
        sleep(Duration::from_secs(10));
        println!("hi1");
    });
    runtime.spawn(async {//相当于tokio::task::spawn
        println!("hi2");//处于单线程中
    });
    println!("hello");
}

这个示例执行的结果是,先输出hello,等待10s,之后输出hi1,再输出hi2

use std::thread::sleep;
use tokio::time::Duration;
 
fn main() {
    //构造单线程tokio运行环境
    let runtime = Builder::new_multi_thread().
        max_threads(1).
        enable_all().
        build().
        expect("create tokio runtime failed");
    runtime.spawn_blocking(|| {//相当于tokio::task::spawn_blocking
        //处于专属线程池中,执行耗时的操作不影响其他任务执行
        sleep(Duration::from_secs(10));
        println!("hi1");
    });
    runtime.spawn(async {//相当于tokio::task::spawn
        println!("hi2");//处于单线程中
    });
    println!("hello");
}

这个示例执行的结果是,先输出hello,之后输出hi2,等待10s,再输出hi2

总结:可以看出tokio任务阻塞和任务不阻塞的功能大致相同。它们的区别是:tokio::task::spawn开启的任务不应执行可能阻塞的操作,这个任务如果阻塞,这个任务运行时的线程就会被阻塞,在这个线程下的其它任务也会被影响到,直到阻塞消除。tokio::task::spawn_blocking开启的任务可以执行阻塞操作,开启的任务运行在一个专属的线程池中,这个任务如果阻塞,不会影响到其它任务的完成。

11.block_in_place使用示例

async fn main() {
    tokio::task::block_in_place(|| {
        println!("hi1");
    });
    tokio::task::block_in_place(|| {
        println!("hi2");
    });
    println!("hello")
}

这个示例的执行结果是:先输出hi1,再输出hi2,最后输出hello

block_in_place作用和spawn_blocking作用类似,不同之处是,前者阻塞当前线程,等待任务完成后,再将当前线程中的其他任务中转移到另外一个线程执行,后者是将当前任务放到专属的线程池中,线程池选择一个线程阻塞等待任务完成,而当前的线程不会被阻塞。

12.yield_now使用示例

async fn main() {
    tokio::task::spawn(async {//任务时间不能超过await任务的时间,超过最后执行
        println!("hi1");//任务所属线程优先级较高,可以抢占到执行所需的资源
    });
    tokio::task::spawn(async {
        tokio::task::yield_now().await;//此处使用让出时间片,等待其他任务完成
        println!("hi2");//一定会执行,使用await会等待任务所属线程先完成,然后执行后续的操作
    }).await.unwrap();
    println!("hello")
}

这个示例的执行结果:先输出hi1,再输出hi2 ,最后输出hello

————————————————
版权声明:本文为CSDN博主「CrazyWorkers」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/CrazyWorkers/article/details/110877643

### 回答1: 我可以为您介绍一下Rust使用MongoDB的步骤:1.安装MongoDB Rust驱动程序;2.使用MongoDB Rust驱动程序连接MongoDB服务器;3.使用MongoDB Rust驱动程序执行CRUD操作。 ### 回答2: Rust是一种系统级编程语言,可以与各种现代数据库进行交互。MongoDB是一个非关系型数据库,在Rust中可以使用第三方库来连接和操作MongoDB。 在Rust使用MongoDB,我们可以使用tokio这样的异步运行时和像mongodb这样的MongoDB驱动。首先,我们需要在Cargo.toml文件中添加mongodb的依赖项,然后使用`tokio`来创建异步运行时。 连接到MongoDB的代码如下: ```rust use mongodb::{Client, options::ClientOptions}; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // 设置MongoDB连接选项 let mut options = ClientOptions::parse("mongodb://localhost:27017").await?; // 创建MongoDB客户端 let client = Client::with_options(options)?; // 连接到数据库 let database = client.database("mydatabase"); // 进行数据库操作 // ... Ok(()) } ``` 通过使用`ClientOptions::parse`函数来解析MongoDB连接URL,并使用`Client::with_options`函数创建MongoDB客户端。然后,我们可以使用`client.database`函数来获取指定数据库的句柄,然后进行进一步的数据库操作。 在Rust使用MongoDB,我们可以执行各种操作,如插入文档、查询文档、更新文档和删除文档等。这些可以通过调用`Database`和`Collection`类型的各种函数来实现。 总结来说,Rust可以通过使用类似tokio和mongodb这样的库与MongoDB进行连接和操作。使用异步运行时和MongoDB驱动,我们可以在Rust中实现与MongoDB的高效交互。 ### 回答3: Rust是一种高效、安全的系统级编程语言,它拥有强大的内存安全性和并发性能。Rust与MongoDB可以很好地结合使用,因为Rust提供了与MongoDB的交互的高性能驱动程序。 在Rust中,我们可以使用第三方库例如"mongodb"来连接和操作MongoDB数据库。这个库提供了实现MongoDB的主要功能,如CRUD操作、索引、聚合管道等。通过使用这个库,我们可以使用Rust编写高性能、线程安全的MongoDB应用程序。 使用Rust编写与MongoDB交互的应用程序,有以下几个优势: 1. 性能优越:Rust被设计为高性能语言,能够利用服务器的所有资源。与其他编程语言相比,Rust在MongoDB应用程序的CPU和内存利用率方面表现出色。 2. 强大的类型系统:Rust的类型系统可以防止内存和并发错误,减少潜在的漏洞和错误。这对于与MongoDB交互的应用程序尤为重要,因为MongoDB是一个大规模、高并发的数据库系统。 3. 原生并发支持:Rust具有一流的并发支持,能够利用多核处理器,提高MongoDB应用程序的处理能力和响应时间。 4. 可靠性:Rust的内存安全特性和静态类型检查能够减少错误和崩溃的可能性。这对于数据持久化和处理敏感数据的MongoDB应用程序尤为重要。 总之,Rust与MongoDB的结合可以实现高性能、安全和可靠的应用程序。通过利用Rust的优势和MongoDB的强大功能,我们可以构建出高效、可扩展的数据库驱动程序和应用程序。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值