当我们在使用tokio和MPSC(多生产者单消费者)通道时,通常以某种固定的方式连接派生线程。然而,在最近项目中,必须在各种配置中动态匹配异步生产者和消费者。
在这篇文章中,让我们来看看如何实现这种非常有用的动态匹配模式。
首先,我们创建一个关于餐厅的Rust项目:
在Cargo.toml文件中加入依赖项:
然后,在src/main.rs文件中写入业务逻辑代码。
作为餐厅经理,可以分配不同的烹饪台来异步准备不同类型的食物,代码如下(现在不用担心未定义的值):
食物应该被送到等待上菜的餐桌上,代码如下:
现在可以组织我们的餐厅了:
为简单起见,我们假设通过应用程序接受订单。例如,餐厅经理(主线程)知道餐桌1正在等待沙拉,餐桌3正在等待汉堡。但如何真正完成这些订单呢?
初级方法:
如果我们强迫经理做这项工作,他可以等待沙拉烹饪站准备沙拉,然后将其传递给餐桌1。然后等待汉堡烹饪台准备好汉堡,把它端到3号餐桌。
这显然是一个有缺陷的设计:
- 不管是否需要,烹饪台都会生产食物。
- 如果烹饪台很慢,那么经理将必须等待食物准备好。
- 经理不应该做繁重的工作,因为这会影响他的反应能力。
我们需要服务员,幸运的是,Tokio为这项工作提供了完美的工具——oneshot 通道。这些通道被设计和优化为一次传递单个值。
为了让服务员先把沙拉送到1号桌,需要修改我们的烹饪台:
其中tokio::sync::mpsc::Receiver<oneshot::Sender<char>>是一个等待队列。是的,你没看错,可以通过其他通道封装一个oneshot通道。当服务员到达烹饪台时,烹饪台就会把食物准备好,然后交给服务员送到餐桌上。让我们对餐桌做同样的事情,他们有特定的服务员接收部分,会给他们送食物:
当服务员被分配到餐桌上时,顾客等待服务员送来烹饪台生产的食物。为了完成这个谜题,我们来修改main函数。经理可以雇佣服务员,而不是自己做繁重的工作,并将他们分配到匹配的烹饪台和桌子上,以完成食物订单。
让我们通过在main函数的末尾添加以下代码来检查这种方式是否有效:
运行结果:
这种通过常规通道发送oneshot通道的模式可以用于实现各种流量控制。以给定的比率、节流等方式传递消息。
完整代码如下:
运行结果: