文盘Rust -- 用Tokio实现简易任务池
作者:京东科技 贾世闻
Tokio 无疑是 Rust 世界中最优秀的异步Runtime实现。非阻塞的特性带来了优异的性能,但是在实际的开发中我们往往需要在某些情况下阻塞任务来实现某些功能。
我们看看下面的例子
fn main(){
let max_task = 1;
let rt = runtime::Builder::new_multi_thread()
.worker_threads(max_task)
.build()
.unwrap();
rt.block_on(async {
println!("tokio_multi_thread ");
for i in 0..100 {
println!("run {}", i);
tokio::spawn(async move {
println!("spawn {}", i);
thread::sleep(Duration::from_secs(2));
});
}
});
}
我们期待的运行结构是通过异步任务打印出99个 “spawn i",但实际输出的结果大概这样
tokio_multi_thread
run 0
run 1
run 2
.......
run 16
spawn 0
run 17
......
run 99
spawn 1
spawn 2
......
spawn 29
......
spawn 58
spawn 59
59执行完后面就没有输出了,如果把max_task设置为2,情况会好一点,但是也没有执行完所有的异步操作,也就是说在资源不足的情况下,Tokio会抛弃某些任务,这不符合我们的预期。那么能不能再达到了某一阀值的情况下阻塞一下,不再给Tokio新的任务呢。这有点类似线程池,当达达最大线程数的时候阻塞后面的任务待有释放的线程后再继续。
我们看看下面的代码。
fn main(){
let max_task = 2;
let rt = runtime::Builder::new_multi_thread()
.worker_threads(max_task)
.enable_time()
.build()
.unwrap();
let mut set = JoinSet::new();
rt.block_on(async {
for i in 0..100 {
println!("run {}", i);
while set.len() >= max_task {
set.join_next().await;
}
set.spawn(async move {
sleep().await;
println!("spawn {}", i);
});
}
while set.len() > 0 {
set.join_next().await;
}
});
}
我们使用JoinSet来管理派生出来的任务。set.join_next().await; 保证至少一个任务被执行完成。结合set的len,我们可以在任务达到上限时阻塞任务派生。当循环结束,可能还有未完成的任务,所以只要set.len()大于0就等待任务结束。
输出大概长这样
running 1 test
tokio_multi_thread
run 0
run 1
spawn 0
run 2
spawn 1
......
run 31
spawn 30
run 32
spawn 31
run 33
......
run 96
spawn 95
run 97
spawn 96
run 98
spawn 97
run 99
spawn 98
spawn 99
符合预期,代码不多,有兴趣的同学可以动手尝试一下。
文盘Rust -- 用Tokio实现简易任务池的更多相关文章
- 文盘Rust -- rust 连接云上数仓 starwift
作者:京东云 贾世闻 最近想看看 rust 如何集成 clickhouse,又犯了好吃懒做的心理(不想自己建环境),刚好京东云发布了兼容ck 的云原生数仓 Starwfit,于是搞了个实例折腾一番. ...
- 文盘Rust -- struct 中的生命周期
最近在用rust 写一个redis的数据校验工具.redis-rs中具备 redis::ConnectionLike trait,借助它可以较好的来抽象校验过程.在开发中,不免要定义struct 中的 ...
- 文盘Rust -- 把程序作为守护进程启动
当我们写完一个服务端程序,需要上线部署的时候,或多或少都会和操作系统的守护进程打交道,毕竟谁也不希望shell关闭既停服.今天我们就来聊聊这个事儿. 最早大家部署应用的通常操作是 "nohu ...
- 文盘Rust -- 给程序加个日志
作者:贾世闻 日志是应用程序的重要组成部分.无论是服务端程序还是客户端程序都需要日志做为错误输出或者业务记录.在这篇文章中,我们结合[log4rs](https://github.com/estk/l ...
- 一文学会Rust?
Rust是什么 Rust 是一个系统编程语言,它注重三个方面:安全,速度和并发性. 特征: 1.没有垃圾回收机制,没有运行时,效率超过c++,直逼c语言 2.内存安全,并发安全,没有空指针 3.极其丰 ...
- 使用Swashbuckle构建RESTful风格文档
本次和大家分享的是Swagger to WebApi的nuget包Swashbuckle:因为项目需要统一api文档的风格,并要支持多种开发语言(C#,java,python),所以首先想到的是swa ...
- Django入门笔记
Django入门笔记 **文档包含Django安装包.学习的笔记.代码等 安装 Django参考附件,只需要把附件拷贝到你需要的目录就行.Django是1.8.16版本 Python:在附件中,其中有 ...
- Git快速入门和常用命令
一.快速入门 本地初始化一个项目 首先,你需要执行下面两条命令,作为 git 的基础配置,作用是告诉 git 你是谁,你输入的信息将出现在你创建的提交中. git config --global us ...
- webassembly
为什么需要 WebAssembly 自从 JavaScript 诞生起到现在已经变成最流行的编程语言,这背后正是 Web 的发展所推动的.Web 应用变得更多更复杂,但这也渐渐暴露出了 JavaScr ...
- SCWS 中文分词
SCWS 中文分词v1.2.3 开源免费的中文分词系统,PHP分词的上乘之选! 首页 下载 演示 文档 关于 服务&支持 API/HTTP 论坛 捐赠 源码@github 文档目录 SCWS- ...
随机推荐
- hdu: You Are the One(区间DP)
Problem Description The TV shows such as You Are the One has been very popular. In order to meet the ...
- mysql 设置相关
告诉mysql客户端这边的文字编码 告诉mysql希望返回的结果集编码: set character_set_client=gbk; set character_set_results=gbk; ...
- oracle中的merge into用法解析
一:merge into的形式 MERGE INTO [target-table] A USING [source-table sql] B ON([conditional expression] a ...
- Ubuntu VMWare安装纪要
一.VMware虚拟机下载与安装 版本:VMware Workstation 16 Pro 二.Ubuntu下载与安装 版本:ubuntu-20.04.2.0-desktop-amd64.iso 三. ...
- 使用npm包API Promise化
- VS Code中使用live Server
live server可以实时查看代码更改后的变化.测试十分快速. 1.安装live server 在扩展中搜索 live server,然后点击安装.等待安装完毕进行下一步配置. 2.打开设置界面: ...
- UniDBGrid控件的几个功能优化
内容自动换行 默认UniDBGrid的cell内的内容如果超出表格列宽并不自动换行和调整行高,给客户带来极大的不方便,通过修改ServerModule的属性CustomCSS可以实现. <sty ...
- 【BUUCTF]ACTF2020 新生赛Exec1write up
根据题目分析,俺们要用ping命令! 打开靶机,输入127.0.0.1尝试提交,直接出现无过滤: 尝试管道符执行命令,常见管道符: 1.|(就是按位或),直接执行|后面的语句 2.||(就是逻辑或), ...
- 【已解决】appium启动会话时遇到的的几种问题
第一种: 1.启动会话时一直卡在加载界面,报错log信息及截图如下 [ADB] Creating ADB subprocess with args: ["-P",5037,&quo ...
- IDEA中使用JDBC连接MySQL数据库报错:No appropriate protocol (protocol is disabled or cipher suites are inappropriate) 的解决方法
在IDEA中使用JDBC连接MySQL,程序运行之后报错: 定位到第16行: 根据上面报错提示,在url参数字段最前面添加参数 useSSL=false : 再次运行程序,成功连接到数据库!