通道(2):接收超时与工作线程退出
区分接收超时、通道断开和业务停止,并通过返回值收集工作结果。
学习日期:2026-10-14。本篇与同日的「通道」其他篇章合计为一个模块、一天学习量。
文中的完整代码保留当前示例的有效语句,省去原文件中的注释与已注释实验行;实验变体另行说明。运行命令在项目根目录执行,示例名称由 Cargo.toml 注册。
recv_timeout:超时、断开与剩余消息
第一次接收等待 100 毫秒,发送端仍存活但没有消息,所以返回 Timeout。随后发送 hello 并成功接收,说明一次接收超时不会关闭通道。
最后发送 最后一条 再释放发送端。由于缓冲里还有消息,这次 recv_timeout 返回 Ok("最后一条"),不会立即报告断开。
use std::sync::mpsc;use std::sync::mpsc::RecvTimeoutError;use std::time::Duration;
fn main() { let (sender, receiver) = mpsc::channel::<String>(); let timeout = Duration::from_millis(100);
match receiver.recv_timeout(timeout) { Ok(message) => println!("收到: {}", message), Err(RecvTimeoutError::Timeout) => println!("等待超时"), Err(RecvTimeoutError::Disconnected) => println!("通道已断开"), }
sender.send(String::from("hello")).unwrap(); println!("超时后仍可接收: {}", receiver.recv().unwrap());
sender.send(String::from("最后一条")).unwrap(); drop(sender);
println!("释放发送端后: {:?}", receiver.recv_timeout(timeout));}运行:
cargo run --example channel_timeout本次本地运行的标准输出如下。并发日志只代表这次运行,先后关系以正文说明为准。
等待超时超时后仍可接收: hello释放发送端后: Ok("最后一条")理解与实验
想观察 Disconnected,可以在最后一次接收后再调用一次 recv_timeout(timeout)。此时没有发送端,也没有待接收消息,才会进入断开分支。
超时是某次等待的结果,断开是端点生命周期导致的状态。100 毫秒是等待参数,不应将程序实际总耗时写成精确的 100 毫秒。
工作线程:用枚举表达任务和停止
Message::Add(i32) 表示累加任务,Message::Stop 表示业务停止请求。工作线程独占 total,依次处理 10 和 20,遇到 Stop 后退出循环,返回 30。
同一个发送端按顺序发送,所以本例的两个累加先于停止被接收。这个顺序不代表来自不同发送线程的所有消息有预定的全局顺序。
use std::sync::mpsc;use std::thread;
enum Message { Add(i32), Stop,}
fn main() { let (sender, reciver) = mpsc::channel();
let handle = thread::spawn(move || { let mut total = 0;
for message in reciver { match message { Message::Add(value) => total += value, Message::Stop => break, } }
total });
sender.send(Message::Add(10)).unwrap(); sender.send(Message::Add(20)).unwrap();
sender.send(Message::Stop).unwrap();
let total = handle.join().unwrap();
println!("处理结果:{}", total); assert_eq!(total, 30);}运行:
cargo run --example worker_basic本次本地运行的标准输出如下。并发日志只代表这次运行,先后关系以正文说明为准。
处理结果:30理解与实验
Stop 是自己定义的业务协议,通道并不识别它;真正让工作线程退出的是 break。发送成功也不表示线程已处理停止消息,仍需 join() 等待实际结束。
另一种结束方式是释放所有发送端,让工作线程处理完剩余消息后自然结束接收循环。这里状态只由工作线程访问,无需再引入共享可变计数器。
同模块笔记
标准库参考
Rust 学习笔记
连载中分享文章
生成精美分享图或复制链接,与更多人分享本文。
继续阅读
换条路线
从其他文章中稳定抽取
最后更新于 ,距今已过 1 天
部分内容可能已过时