ผู้ผลิต/ผู้บริโภค สายงาน และการหมดเวลา
สร้าง ผู้ผลิต/ผู้บริโภค อย่างง่าย ประกอบ สายงาน ด้วย AsyncSequence และใช้การแข่งกับงาน sleep เพื่อสร้าง การหมดเวลา
ผู้ผลิต/ผู้บริโภค สายงาน และการหมดเวลา เป็นบทเรียน Swift Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Swift Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Swift Academy มีบทเรียนทั้งหมด 3 บทเรียน
สิ่งที่จะสร้าง
บทเรียนนี้แสดงรูปแบบสามประการ:
- ผู้ผลิต/ผู้บริโภค ด้วย AsyncStream
- กระบวนการประมวลผลต่อเนื่อง โดยใช้การแปลงของ AsyncSequence
- การหมดเวลา ด้วยการแข่งกันของงานแบบร่วมมือกัน
ผู้ผลิตและผู้บริโภคเบื้องต้น
AsyncStream เชื่อมผู้ผลิตแบบผลักเข้ากับการบริโภคแบบดึงด้วย การวนรอ
// 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
- ใช้การแข่งกันของงานและยกเลิกฝ่ายที่แพ้เพื่อจัดการ การหมดเวลา
คำถามที่พบบ่อย
บทเรียน “ผู้ผลิต/ผู้บริโภค สายงาน และการหมดเวลา” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ผู้ผลิต/ผู้บริโภค สายงาน และการหมดเวลา” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Swift Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Swift Academy มีบทเรียนทั้งหมด 3 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ผู้ผลิต/ผู้บริโภค สายงาน และการหมดเวลา”
สร้าง ผู้ผลิต/ผู้บริโภค อย่างง่าย ประกอบ สายงาน ด้วย AsyncSequence และใช้การแข่งกับงาน sleep เพื่อสร้าง การหมดเวลา คุณปฏิบัติ Swift Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Swift Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Swift Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 3 บทเรียน
บทเรียน “ผู้ผลิต/ผู้บริโภค สายงาน และการหมดเวลา” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Swift Academy นี้ได้ไหม
ได้ บทเรียน Swift Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ผู้ผลิต/ผู้บริโภค สายงาน และการหมดเวลา
- การเชื่อมโค้ดเรียกกลับเดิม/Combine เข้ากับ async/await
- การทดสอบโค้ด async (XCTest)