Tokio开启多个tokio-runtime-w线程是否正常?能否限制?
Tokio开启大量线程是否正常?
先看你提供的top输出:
top - 19:50:25 up 5:55, 2 users, load average: 0.00, 0.00, 0.00 Threads: 9 total, 0 running, 9 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st MiB Mem : 19963.7 total, 19046.5 free, 268.3 used, 648.9 buff/cache MiB Swap: 0.0 total, 0.0 free, 0.0 used. 19449.8 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1665 root 20 0 17556 4 0 S 0.0 0.0 0:00.00 nfwd 1666 root 20 0 17556 4 0 S 0.0 0.0 0:00.00 tokio-runtime-w 1667 root 20 0 17556 4 0 S 0.0 0.0 0:00.00 tokio-runtime-w 1668 root 20 0 17556 4 0 S 0.0 0.0 0:00.00 tokio-runtime-w 1669 root 20 0 17556 4 0 S 0.0 0.0 0:00.00 tokio-runtime-w 1670 root 20 0 17556 4 0 S 0.0 0.0 0:00.00 tokio-runtime-w 1671 root 20 0 17556 4 0 S 0.0 0.0 0:00.00 tokio-runtime-w 1672 root 20 0 17556 4 0 S 0.0 0.0 0:00.00 tokio-runtime-w 1673 root 20 0 17556 4 0 S 0.0 0.0 0:00.00 tokio-runtime-w
你提到仅用tokio::net::UnixListener监听,却出现8个tokio-runtime-w线程,以下是具体分析:
现象原因
这是Tokio的默认行为:当你使用#[tokio::main]注解时,Tokio会自动初始化一个多线程工作池,默认线程数等于你的系统CPU核心数(你看到的8个线程说明你的机器是8核)。这些线程是runtime预创建的,用于处理后续可能的异步任务,哪怕当前只有监听逻辑,runtime也会提前准备好这些资源。
这些线程是否必要?
分场景来看:
- 对于需要处理大量并发任务(比如多连接处理、CPU密集型异步逻辑)的场景,这些线程是必要的——它们能充分利用多核CPU的并行能力,提升整体吞吐量,同时避免动态创建线程的开销。
- 如果你的业务逻辑极端简单(比如仅监听一个套接字,没有任何其他并发任务),这些线程属于预分配的闲置资源,此时可以考虑调整。
如何限制或省略这些线程?
你可以通过自定义Tokio runtime来控制线程数量:
1. 使用单线程runtime
如果不需要多线程,直接切换到单线程模式,这样只会产生一个线程:
#[tokio::main(flavor = "current_thread")] async fn main() -> Result<(), Box<dyn Error>> { let mut stream = StreamServer::new().await?; stream.run().await?; }
2. 自定义多线程runtime的线程数
如果需要多线程但想限制数量,手动创建runtime并指定工作线程数:
use tokio::runtime::Builder; fn main() -> Result<(), Box<dyn Error>> { // 指定工作线程数为2,可根据需求调整 let runtime = Builder::new_multi_thread() .worker_threads(2) .build()?; runtime.block_on(async { let mut stream = StreamServer::new().await?; stream.run().await?; Ok(()) }) }
额外提示:你的代码bug修正
注意你提供的StreamServer::run方法里有个错误:在Ok((stream, addr))分支中,你误用了self.stream(而self根本没有这个字段),应该用刚接收的stream变量。修正后的代码片段:
pub async fn run(&mut self) -> Result<(), Box<dyn Error>> { loop { match self.socket.accept().await { Ok((mut stream, _addr)) => loop { match stream.readable().await { Ok(()) => { let mut buf = Vec::with_capacity(1024); match stream.try_read_buf(&mut buf) { Ok(n) if n > 0 => { let msg = String::from_utf8((&buf[..n]).to_vec())?; println!("收到消息: {}", msg); Ok(()) } Ok(_) => Ok(()), Err(ref e) if e.kind() == ErrorKind::WouldBlock => continue, Err(e) => return Err(e.into()), } } Err(e) => return Err(e.into()), } }, Err(ref e) if e.kind() == ErrorKind::WouldBlock => continue, Err(e) => return Err(e.into()), }; } }
内容的提问来源于stack exchange,提问作者Nkk
相关产品推荐
相关产品推荐

