【tokio】spawn

tokio::spawn

原型

pub fn spawn<T>(task: T) -> JoinHandle<T::Output> 
where
    T: Future + Send + 'static,
    T::Output: Send + 'static,

spawn派生一个异步任务,并返回一个JoinHandle,用于与异步任务交互。如调用await获取返回值。

派生任务使该任务能够与其他任务并发执行。派生的任务可以在当前线程上执行,也可以发送到另一个线程执行。具体内容取决于当前的运行时配置。

不能保证派生的任务将执行到完成。当运行时关闭时,无论该任务的生命周期如何,所有未完成的任务都将被丢弃。

例子

#[tokio::main]
async fn main() {
    let handle = tokio::spawn(async {
        // Do some async work
        "return value"
    });

    // Do some other work
    println!("Do some other work");
    
    let out = handle.await.unwrap();
    println!("GOT {}", out);
}

并行和协程

并行编程:每次启动新线程处理任务。

协程编程:tokio提供的是协程编程。tokio::spawn() 并不是启动一个新的线程,只是使用 Tokio 所建立的线程池,Tokio 会管理调度这些被启动的任务,而不需要程序员的参与。在标准库的基础上,Tokio 也提供了一些并行常用的同步工具,比如信号量(Semaphore)。

相同点:

协程和并行都是通过同时执行多个任务来提高性能

不同点:

本质不同。协程是在由于 IO 造成等待时去执行其他计算任务来提高系统资源的利用率,而并行只是挖掘硬件本身所提供的额外计算资源,并不处理 IO 等待的时间浪费。

'static

派生任务的生命周期必须是’static。

也就是说任务中不能引用任何外部数据。

下面编译失败,派生任务引用了v。

use tokio::task;

#[tokio::main]
async fn main() {
    let v = vec![1, 2, 3];

    task::spawn(async {
        println!("Here's a vec: {:?}", v);
    });
}

move

通过move,可将外部变量移动到任务中。如果需要从多个任务同时访问单个数据,则必须使用Arc等同步原语来共享该数据。

例子

use tokio::task;

#[tokio::main]
async fn main() {
    let v = vec![1, 2, 3];

    task::spawn(async move {
        println!("Here's a vec: {:?}", v);
    }).await;
}

Send

派生任务需要实现send方法。

这将使Tokio运行时在线程之间移动任务,而这些任务在.aWait挂起。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用 Rust 中的 tokio 和 warp 库同时监听 WebSocket 和 HTTP 请求的示例代码: ```rust use std::net::SocketAddr; use warp::Filter; use tokio::sync::broadcast; use tokio_stream::wrappers::BroadcastStream; use tokio_tungstenite::tungstenite::protocol::Message; use tokio_tungstenite::{WebSocketStream, MaybeTlsStream}; use tokio_tungstenite::tungstenite::handshake::server::Request; async fn handle_ws( ws: WebSocketStream<MaybeTlsStream<tokio::net::TcpStream>>, tx: broadcast::Sender<Message>, ) { let (mut ws_tx, mut ws_rx) = ws.split(); let (tx_clone, mut rx) = tx.subscribe(); tokio::spawn(async move { while let Some(message) = rx.recv().await { if let Err(e) = ws_tx.send(message).await { eprintln!("websocket send error: {}", e); break; } } }); while let Some(Ok(message)) = ws_rx.next().await { if let Err(e) = tx_clone.send(message).unwrap() { eprintln!("broadcast send error: {}", e); break; } } } #[tokio::main] async fn main() { let (tx, _) = broadcast::channel(16); let ws_route = warp::path("ws") .and(warp::ws()) .map(move |ws: warp::ws::Ws| { let tx = tx.clone(); ws.on_upgrade(move |websocket| handle_ws(websocket, tx)) }); let http_route = warp::path("hello") .map(|| "Hello, world!"); let routes = ws_route.or(http_route); let addr = SocketAddr::from(([0, 0, 0, 0], 8080)); warp::serve(routes).run(addr).await; } ``` 在这个示例中,我们使用 `tokio_tungstenite` 库来创建 WebSocket 服务器,使用 `warp` 库创建 HTTP 服务器。在 `handle_ws` 函数中,我们使用 `tokio::sync::broadcast` 来实现将 WebSocket 消息广播给所有连接的客户端。最后,我们将 WebSocket 和 HTTP 的路由组合在一起,并使用 `warp::serve` 启动服务器。 需要注意的是,使用同一端口同时监听 WebSocket 和 HTTP 请求并不是一个标准做法,因为 WebSocket 协议需要和 HTTP 协议进行握手,并且 WebSocket 协议有自己的帧格式和消息语义。因此,如果你需要同时支持 WebSocket 和 HTTP 请求,最好是使用不同的端口或使用不同的路径进行区分。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值