Функция spawn
Источник: Документация smol::spawn
#![allow(unused)] fn main() { pub fn spawn<T: Send + 'static>( future: impl Future<Output = T> + Send + 'static, ) -> Task<T> }
Запускает задачу в глобальном исполнителе (по умолчанию однопоточном).
Описание
Существует глобальный исполнитель, который лениво инициализируется при первом использовании. Он включен в эту библиотеку для удобства при написании модульных тестов и небольших программ, но в остальных случаях более целесообразно создавать собственный Executor.
По умолчанию глобальный исполнитель запускается одним фоновым потоком, но вы также можете настроить количество потоков, установив переменную окружения SMOL_THREADS.
Поскольку исполнитель сохраняется навсегда, метод drop не вызывается для задач при выходе из программы.
Примеры
#![allow(unused)] fn main() { let task = smol::spawn(async { 1 + 2 }); smol::block_on(async { assert_eq!(task.await, 3); }); }
Особенности
Глобальный исполнитель
- Ленивая инициализация: Создается при первом вызове
spawn - Конфигурация потоков: Настраивается через переменную окружения
SMOL_THREADS - Постоянное существование: Исполнитель не уничтожается при завершении программы
Требования к задачам
T: Send + 'static- результат должен быть передаваемым между потоками и иметь статическое время жизниfuture: Send + 'static- фьючерс должен быть передаваемым и иметь статическое время жизни
Примеры использования
Базовая задача
#![allow(unused)] fn main() { use smol::{spawn, block_on}; let task = spawn(async { println!("Задача выполняется"); 42 }); let result = block_on(async { task.await }); assert_eq!(result, 42); }
Параллельные задачи
#![allow(unused)] fn main() { use smol::{spawn, block_on}; let task1 = spawn(async { 1 + 2 }); let task2 = spawn(async { 3 + 4 }); let (result1, result2) = block_on(async { (task1.await, task2.await) }); assert_eq!(result1, 3); assert_eq!(result2, 7); }
Долгоиграющие задачи
#![allow(unused)] fn main() { use smol::{spawn, Timer}; use std::time::Duration; let task = spawn(async { for i in 0..5 { println!("Итерация {}", i); Timer::after(Duration::from_secs(1)).await; } "Завершено" }); // Задача продолжит выполняться в фоне даже без ожидания }
Настройка через переменные окружения
# Запуск с 4 рабочими потоками
SMOL_THREADS=4 cargo run
# Запуск с 1 потоком (по умолчанию)
SMOL_THREADS=1 cargo run
Рекомендации по использованию
Когда использовать
- Тестирование: Удобно для модульных тестов
- Прототипирование: Быстрое создание прототипов
- Небольшие программы: Простые приложения и утилиты
Когда не использовать
- Производственные приложения: Лучше создавать собственный
Executor - Специфичные требования: При необходимости тонкой настройки
- Длительные процессы: Из-за особенностей управления временем жизни
Альтернативы
Для более сложных сценариев рекомендуется использовать:
#![allow(unused)] fn main() { use smol::Executor; let executor = Executor::new(); let task = executor.spawn(async { // ваша задача }); }
Безопасность
- Send + 'static: Гарантирует безопасность между потоками
- Глобальное состояние: Исполнитель существует всю жизнь программы
- Автоматическое управление: Не требуется ручное уничтожение задач