任务
鉴于任务运行异步逻辑位,它们由Future特征表示。 任务完成处理后,任务的实现将以()值完成。
任务被传递给执行程序,执行程序处理任务的调度。 执行程序通常在一组或一组线程中调度许多任务。 任务不得执行计算繁重的逻辑,否则将阻止其他任务执行 。 因此,不要尝试将斐波那契序列计算为任务。
任务通过直接实施Future特征或通过使用future
和tokio crate中可用的各种组合函数构建future
来实现。
下面是一个使用HTTP get从URI获取值并缓存结果的示例。
- 如果没有条目,请执行HTTP get。
- 将响应存储在缓存中。
由于这些步骤对于完成任务都是必需的,因此将它们全部分组到同一任务中是有意义的。
就像Go和Erlang一样,任务可以使用消息传递进行通信。 实际上,使用消息传递来协调多个任务是很常见的。 这允许独立任务仍然相互作用。
包提供了一个同步模块,其中包含一些适合跨任务传递消息的通道类型。
- oneshot是一个用于发送一个值的通道。
- mpsc是用于发送许多(零个或多个)值的通道。
前面的例子并不完全正确。 鉴于任务同时执行,无法保证缓存更新任务在其他任务尝试从缓存中读取时将第一个值写入缓存。
这是使用消息传递的完美情况。 高速缓存更新任务可以发送消息,通知其他任务它已使用初始值启动了高速缓存。
任务通知
使用Tokio构建的应用程序被构造为一组并发运行的任务。 这是服务器的基本结构:
在这种情况下,我们为每个入站服务器套接字生成一个任务。 但是,也可以实现处理同一套接字上所有入站连接的服务器future:
通知发生在任务级别。 该任务不知道哪个子future
触发了通知。 因此,无论何时轮询任务,都必须尝试轮询所有子future
。
在此任务中,有三个子可以进行轮询。 如果其中一个子future
所包含的资源转为“就绪”,则任务本身会收到通知,并会尝试轮询其所有三个子future
。 其中一个将推进,这反过来推进任务的内部状态。
关键是尽量减少任务,尽可能少地完成每项任务。 这就是为什么服务器为每个连接生成新任务而不是在与侦听器相同的任务中处理连接的原因。
好吧,实际上有一种方法可以让任务知道哪个子使用FuturesUnordered触发了通知,但通常正确的做法是生成一个新任务。