Rust从入门到实战系列二百五十:在 new 中验证池中线程数量

这里仍然存在警告是因为其并没有对 new 和 execute 的参数做任何操作。让我们用期望的行为来实现
这些函数。以考虑 new 作为开始。之前选择使用无符号类型作为 size 参数的类型,因为线程数为负的
线程池没有意义。然而,线程数为零的线程池同样没有意义,不过零是一个完全有效的 u32 值。让我们
增加在返回 ThreadPool 实例之前检查 size 是否大于零的代码,并使用 assert! 宏在得到零时 panic,如
示例 20-13 所示:
文件名: src∕lib.rs

pub struct ThreadPool;

impl ThreadPool {
/// 创建线程池。
///
/// 线程池中线程的数量。
///
/// # Panics
///
/// new 函数在 size 为 0 时会 panic。
pub fn new(size: usize) -> ThreadPool {
assert!(size > 0);
ThreadPool
}
// --snip–

pub fn execute(&self, f: F)

where

F: FnOnce() + Send + 'static,

{

20.2. 将单线程 SERVER 变为多线程 SERVER 543

}

}
示例 20-13: 实现 ThreadPool::new 在 size 为零时 panic
这里用文档注释为 ThreadPool 增加了一些文档。注意这里遵循了良好的文档实践并增加了一个部分来
提示函数会 panic 的情况,正如第十四章所讨论的。尝试运行 cargo doc −−open 并点击 ThreadPool
结构体来查看生成的 new 的文档看起来如何!
相比像这里使用 assert! 宏,也可以让 new 像之前 I∕O 项目中示例 12-9 中 Config::new 那样返回一个
Result,不过在这里我们选择创建一个没有任何线程的线程池应该是不可恢复的错误。如果你想做的更
好,尝试编写一个采用如下签名的 new 版本来感受一下两者的区别:
pub fn new(size: usize) -> Result<ThreadPool, PoolCreationError> {
分配空间以储存线程
现在有了一个有效的线程池线程数,就可以实际创建这些线程并在返回之前将他们储存在 ThreadPool
结构体中。不过如何 ” 储存” 一个线程?让我们再看看 thread::spawn 的签名:
pub fn spawn<F, T>(f: F) -> JoinHandle
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
spawn 返回 JoinHandle,其中 T 是闭包返回的类型。尝试使用 JoinHandle 来看看会发生什么。在
我们的情况中,传递给线程池的闭包会处理连接并不返回任何值,所以 T 将会是单元类型 ()。
示例 20-14 中的代码可以编译,不过实际上还并没有创建任何线程。我们改变了 ThreadPool 的定义来
存放一个 thread::JoinHandle<()> 的 vector 实例,使用 size 容量来初始化,并设置一个 for 循环了来运
行创建线程的代码,并返回包含这些线程的 ThreadPool 实例:
文件名: src∕lib.rs
use std::thread;
pub struct ThreadPool {
threads: Vec<thread::JoinHandle<()>>,
}
impl ThreadPool {
// --snip–

/// Create a new ThreadPool.

///

/// The size is the number of threads in the pool.

///

/// # Panics

///

/// The new function will panic if the size is zero.

pub fn new(size: usize) -> ThreadPool {
assert!(size > 0);
let mut threads = Vec::with_capacity(size);
for _ in 0…size {
// create some threads and store them in the vector
544 CHAPTER 20. 最后的项目: 构建多线程 WEB SERVER
}
ThreadPool { threads }
}
// --snip–

pub fn execute(&self, f: F)

where

F: FnOnce() + Send + 'static,

{

}

}
示例 20-14: 为 ThreadPool 创建一个 vector 来存放线程
这里将 std:: thread 引入库 crate 的作用域,因为使用了 thread::JoinHandle 作为 ThreadPool 中 vector
元素的类型。
在得到了有效的数量之后,ThreadPool 新建一个存放 size 个元素的 vector。本书还未使用过 with_capacity,
它与 Vec::new 做了同样的工作,不过有一个重要的区别:它为 vector 预先分配空间。因为已经知道了
vector 中需要 size 个元素,预先进行分配比仅仅 Vec::new 要稍微有效率一些,因为 Vec::new 随着插
入元素而重新改变大小。
如果再次运行 cargo check,会看到一些警告,不过应该可以编译成功。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值