Colas de tareas en Rust: guía completa para principiantes

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: ¿para qué sirven las colas de tareas en Rust?

Al desarrollar aplicaciones en Rust, a menudo surge la necesidad de procesar tareas de forma asíncrona o distribuir la carga entre varios hilos. Una cola de tareas (task queue) es una estructura de datos fundamental que permite organizar el procesamiento secuencial o concurrente de unidades de trabajo. En este artículo, analizaremos cómo crear y utilizar colas de tareas en Rust, comenzando con ejemplos simples y llegando hasta escenarios reales.

Rust ofrece varios enfoques para implementar colas: desde canales estándar de std::sync::mpsc hasta soluciones asíncronas avanzadas basadas en tokio. Revisaremos cada uno de ellos y mostraremos cómo elegir la herramienta adecuada para tu tarea.



Fundamentos: cola de tareas mediante canales mpsc

La forma más sencilla de crear una cola de tareas en Rust es utilizar un canal multiproductor y un solo consumidor (mpsc) de la biblioteca estándar. Este mecanismo es ideal para situaciones en las que un hilo procesa tareas enviadas desde varios hilos productores.



Creación de una cola simple

Veamos un ejemplo básico donde el hilo principal envía tareas y un hilo separado las procesa:

use std::sync::mpsc;use std::thread;use std::time::Duration;

fn main() { // Creamos el canal: transmisor y receptor let (tx, rx) = mpsc::channel::<String>();

// Iniciamos el hilo procesador let handler = thread::spawn(move || { for task in rx { println!("Procesando tarea: {}", task); thread::sleep(Duration::from_millis(500)); } });

// Enviamos las tareas let tasks = vec!["Tarea 1", "Tarea 2", "Tarea 3"]; for task in tasks { tx.send(task.to_string()).unwrap(); println!("Enviado: {}", task); }

// Cerramos el canal para que el procesador termine drop(tx); handler.join().unwrap();}

Este código demuestra la mecánica básica: tx.send() coloca una tarea en la cola, y el receptor rx las extrae en orden de llegada (FIFO). Observa que el canal bloquea automáticamente al productor si la cola está llena, y bloquea al consumidor si la cola está vacía.



Múltiples productores

Una de las principales ventajas de mpsc es la posibilidad de clonar el transmisor para varios hilos:

use std::sync::mpsc;use std::thread;

fn main() { let (tx, rx) = mpsc::channel::<u32>(); let mut handles = vec![];

// Iniciamos 3 hilos productores for id in 0..3 { let tx_clone = tx.clone(); handles.push(thread::spawn(move || { for i in 0..5 { let task = id * 100 + i; tx_clone.send(task).unwrap(); } })); }

// Cerramos el transmisor original drop(tx);

// Procesamos todas las tareas for received in rx { println!("Tarea recibida: {}", received); }

for handle in handles { handle.join().unwrap(); }}

Cada productor envía sus tareas, y un único consumidor las procesa en orden de llegada. Este es el patrón clásico "productor-consumidor".



Cola avanzada con prioridades

El canal estándar mpsc no admite prioridades: las tareas se procesan estrictamente en el orden de envío. Sin embargo, podemos implementar una cola con prioridades usando BinaryHeap de la biblioteca estándar.



Implementación de una cola prioritaria

use std::collections::BinaryHeap;use std::cmp::Ordering;

#[derive(Debug, Eq, PartialEq)]struct Task { priority: u8, data: String,}

impl Ord for Task { fn cmp(&self, other: &Self) -> Ordering { // Cuanto menor es el número, mayor es la prioridad other.priority.cmp(&self

Blogs

Book Recommendations