Производитель и потребитель, конвейеры, тайм-ауты
Создайте простой механизм производитель/потребитель , объединяйте конвейеры с помощью AsyncSequence и реализуйте тайм-аут , состязая задачу сна с основной задачей.
«Производитель и потребитель, конвейеры, тайм-ауты» — бесплатный урок Swift Academy на CoddyKit. Это урок 1 из 3. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Swift Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Swift Academy содержит 3 уроков всего.
Что Вы создадите
В этом уроке рассматриваются три шаблона:
- Производитель/потребитель с использованием AsyncStream
- Конвейеры с преобразованиями AsyncSequence
- Ограничения времени с помощью согласованного соперничества задач
Базовый производитель/потребитель
AsyncStream связывает производителей, работающих по модели передачи данных, с потреблением через for await, основанным на запросе данных.
// Producer pushes values; consumer iterates them asynchronously.
func makeNumbers(count: Int) -> AsyncStream<Int> {
AsyncStream { continuation in
Task {
for i in 1...count {
continuation.yield(i)
try? await Task.sleep(nanoseconds: 40_000_000) // ~40ms
}
continuation.finish()
}
}
}
Task {
let stream = makeNumbers(count: 5)
for await n in stream {
print("consume:", n)
}
print("done") // after finish()
}Политика противодавления
Выберите bufferingPolicy, чтобы управлять противодавлением: отбрасывать самые старые или самые новые элементы либо использовать неограниченный буфер для небольших потоков.
// Use a limited buffering policy to avoid memory spikes.
func makeBufferedNumbers(limit: Int) -> AsyncStream<Int> {
AsyncStream(bufferingPolicy: .bufferingOldest(limit)) { cont in
Task {
for i in 1...20 {
cont.yield(i)
// Producer is fast; buffer prevents unbounded growth
}
cont.finish()
}
}
}
Task {
let s = makeBufferedNumbers(limit: 5)
for await n in s {
// Simulate a slow consumer
try? await Task.sleep(nanoseconds: 60_000_000)
print("got:", n)
}
}Конвейер с AsyncSequence
AsyncSequence поддерживает знакомые операторы (преобразование, фильтрация, reduce), поэтому Вы можете создавать понятные потоковые конвейеры.
// Compose a pipeline: map -> filter -> reduce over an AsyncSequence.
func numbers(_ n: Int) -> AsyncStream<Int> {
AsyncStream { cont in
Task {
for i in 1...n { cont.yield(i) }
cont.finish()
}
}
}
Task {
let evensSquaredSum = await numbers(10)
.map { $0 * $0 }
.filter { $0.isMultiple(of: 2) }
.reduce(0, +)
print("sum:", evensSquaredSum) // 220 (4+16+36+64+100)
}Параллельный этап
Используйте группы задач внутри конвейеров для преобразований, ограниченных возможностями CPU, а затем объединяйте результаты в удобном для Вас порядке.
// Fan-out/fan-in: process items concurrently, then merge.
// Here we use a task group to transform elements in parallel.
func parallelUppercased(_ input: [String]) async -> [String] {
await withTaskGroup(of: String.self) { group in
for s in input {
group.addTask {
try? await Task.sleep(nanoseconds: 30_000_000)
return s.uppercased()
}
}
return await group.reduce(into: [String]()) { $0.append($1) }
}
}
Task {
let out = await parallelUppercased(["a","bb","ccc"])
print(out) // ["A","BB","CCC"]
}Вспомогательная функция ограничения времени
Реализуйте ограничение времени, запустив операцию одновременно с задачей sleep; выполните cancel проигравшей задачи, чтобы не тратить ресурсы.
enum TimeoutError: Error { case timedOut }
func withTimeout<T>(
seconds: Double,
operation: @escaping () async throws -> T
) async throws -> T {
try await withThrowingTaskGroup(of: T.self) { group in
// Child 1: actual work
group.addTask { try await operation() }
// Child 2: the timer
group.addTask {
try await Task.sleep(nanoseconds: UInt64(seconds * 1_000_000_000))
throw TimeoutError.timedOut
}
// First child to finish wins; cancel the rest
let result = try await group.next()!
group.cancelAll()
return result
}
}
// Demo
func slowFetch() async throws -> String {
try await Task.sleep(nanoseconds: 300_000_000) // 300ms
return "OK"
}
Task {
do {
let v = try await withTimeout(seconds: 0.1) { try await slowFetch() }
print("value:", v)
} catch {
print("timeout:", error) // expected
}
}Шаблон ограничения времени (гонка)
Быстрая проверка: как лучше всего добавить ограничение времени?
Итоги
Итоги:
- Используйте AsyncStream для модели производителя/потребителя.
- Составляйте конвейеры AsyncSequence с преобразованием, фильтрацией и reduce.
- Реализуйте ограничения времени, устраивая гонку задач и выполняя cancel проигравшей задачи.
Часто задаваемые вопросы
Урок «Производитель и потребитель, конвейеры, тайм-ауты» бесплатный?
Да — полный текст урока «Производитель и потребитель, конвейеры, тайм-ауты» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Swift Academy, подпишись на CoddyKit PRO. Курс Swift Academy содержит 3 уроков всего.
Чему я научусь в уроке «Производитель и потребитель, конвейеры, тайм-ауты»?
Создайте простой механизм производитель/потребитель , объединяйте конвейеры с помощью AsyncSequence и реализуйте тайм-аут , состязая задачу сна с основной задачей. Ты практикуешь Swift Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Swift Academy?
Предыдущий опыт не требуется. Swift Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 3.
Сколько времени занимает урок «Производитель и потребитель, конвейеры, тайм-ауты»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Swift Academy?
Да. Каждый урок Swift Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Производитель и потребитель, конвейеры, тайм-ауты
- Переход от устаревших обратных вызовов и Combine к async/await
- Тестирование асинхронного кода (XCTest)