Coroutines (โครูทีน) คือเธรดน้ำหนักเบาใน Kotlin สำหรับการเขียนโปรแกรมแบบอะซิงโครนัส ซึ่งพร้อมใช้งานผ่านไลบรารี kotlinx.coroutines ตาม JetBrains Kotlin Documentation, 2026, Coroutines ช่วยให้สามารถระงับการทำงานของฟังก์ชันโดยไม่บล็อกเธรด ซึ่งแตกต่างจาก Thread แบบดั้งเดิม โครูทีนทำงานบนพูลเธรดที่จำกัด ทำให้มีน้ำหนักเบากว่าเธรดทั่วไปเป็นพันเท่า Kotlin Coroutines ถูกผสานรวมอย่างสมบูรณ์กับ Android Jetpack, Retrofit, Room และไลบรารียอดนิยมอื่น ๆ ในระบบนิเวศของ Android
ประเด็นสำคัญ
Coroutines เป็นกลไกการเขียนโปรแกรมแบบอะซิงโครนัสใน Kotlin ที่ทำงานในไลบรารี kotlinx.coroutines ซึ่งแตกต่างจากเธรดของระบบปฏิบัติการ โครูทีนไม่ได้ผูกติดกับเธรดเฉพาะ: สามารถหยุดชั่วคราวบนเธรดหนึ่งและดำเนินต่อบนอีกเธรดหนึ่งได้ เธรดเดียวสามารถทำงานโครูทีนได้หลายพันตัว โดยสลับระหว่างกันด้วยค่าใช้จ่ายเพียงเล็กน้อย
โครูทีนปรากฏใน Kotlin 1.3 (2018) เป็นฟีเจอร์ทดลองและกลายเป็นเสถียรใน Kotlin 1.5 (2021) Coroutines แก้ปัญหา callback hell ในลักษณะเดียวกับ async/await แต่ให้ API ที่สมบูรณ์กว่า: ช่องสัญญาณ (Channel), Flow, การจัดการข้อยกเว้นในลำดับชั้น Job และการผสานรวมโดยตรงกับ Android Lifecycle
ตามข้อมูลของ JetBrains (2025) โครูทีนแต่ละตัวใช้หน่วยความจำประมาณ 100 ไบต์ ในขณะที่เธรดทั่วไปใช้ 1+ MB ซึ่งทำให้สามารถเรียกใช้โครูทีนหลายล้านตัวในแอปพลิเคชันเดียวโดยไม่มีความเสี่ยง OutOfMemoryError ความเบาของโครูทีนนี่เองที่ทำให้เป็นเครื่องมือที่ต้องการสำหรับการทำงานแบบอะซิงโครนัสใน Android
โครูทีน Kotlin แต่ละตัวถูกคอมไพล์เป็นเครื่องสถานะผ่าน Continuation Passing Style (CPS) คอมไพเลอร์เพิ่มพารามิเตอร์ Continuation ที่ซ่อนอยู่ให้กับทุกฟังก์ชัน suspend Continuation ประกอบด้วยจุดดำเนินต่อและตัวแปรท้องถิ่นทั้งหมด เมื่อโครูทีนหยุดชั่วคราว runtime จะบันทึก Continuation และเมื่อดำเนินต่อ จะกู้คืนบนเธรดใด ๆ ที่มีอยู่ในพูล Dispatcher
suspend คือคำสำคัญของ Kotlin ที่ทำเครื่องหมายฟังก์ชันว่าระงับได้ ฟังก์ชันดังกล่าวสามารถเรียกได้จากฟังก์ชัน suspend อื่นหรือจากโครูทีนเท่านั้น ภายในฟังก์ชัน suspend คุณสามารถเรียกฟังก์ชัน suspend อื่น ๆ ในลำดับใดก็ได้ และแต่ละจุดเรียกเป็นจุดที่อาจเกิดการระงับ
กลไกง่าย ๆ: เมื่อฟังก์ชัน suspend เรียกฟังก์ชัน suspend อื่น มันจะหยุดชั่วคราวที่จุดนั้น ปล่อยเธรด หลังจากฟังก์ชันที่ถูกเรียกเสร็จสิ้น runtime จะดำเนินการต่อจากตำแหน่งที่บันทึกไว้ สิ่งนี้เรียกว่าการยกเลิกแบบร่วมมือ (cooperative cancellation) — ไม่มีเธรดใดถูกบล็อก
สำคัญ: ฟังก์ชัน suspend ไม่ได้เป็นอะซิงโครนัสโดยค่าเริ่มต้น ลำดับการทำงานยังคงเป็นลำดับหากไม่ได้ใช้ launch หรือ async suspend เพียงอนุญาตให้ฟังก์ชันหยุดชั่วคราวโดยไม่บล็อกเธรดและเป็นส่วนหนึ่งของบริบทโครูทีน Continuation Passing Style เป็นโมเดลการคอมไพล์ที่ฟังก์ชัน suspend แต่ละตัวรับ callback Continuation ที่ซ่อนอยู่ และคอมไพเลอร์สร้างเครื่องสถานะเพื่อจัดการการหยุดชั่วคราวและการดำเนินต่อ
CoroutineScope คือบริบทที่กำหนดวงจรชีวิตของโครูทีน โครูทีนทั้งหมดต้องถูกเริ่มภายในขอบเขต เมื่อขอบเขตถูกยกเลิก (เช่น เมื่อ Activity สิ้นสุด) โครูทีนลูกทั้งหมดจะถูกยกเลิกโดยอัตโนมัติ ซึ่งป้องกันการรั่วไหลของงานเบื้องหลัง Android Jetpack มีขอบเขตพร้อมใช้สำหรับแต่ละคอมโพเนนต์: viewModelScope สำหรับ ViewModel และ lifecycleScope สำหรับ Activity และ Fragment ซึ่งจะถูกยกเลิกโดยอัตโนมัติเมื่อคอมโพเนนต์ที่เกี่ยวข้องถูกทำลาย
การทำงานพร้อมกันแบบมีโครงสร้าง (Structured Concurrency) เป็นหลักการที่รับประกันว่าโครูทีนจะไม่เสร็จสมบูรณ์จนกว่าโครูทีนลูกทั้งหมดจะเสร็จสมบูรณ์ ลำดับชั้น Job ก่อตัวเป็นต้นไม้: โครูทีนรากสร้าง parent job ลูกสร้าง child jobs การยกเลิก parent job แพร่กระจายไปยังลูกทั้งหมด Structured Concurrency คือความแตกต่างพื้นฐานระหว่างโครูทีนและเธรด
| Scope | ใช้ที่ไหน | การยกเลิก |
|---|---|---|
| GlobalScope | เฉพาะงานเดมอน | ไม่ถูกยกเลิกอัตโนมัติ |
| viewModelScope | Android ViewModel | เมื่อล้าง ViewModel |
| lifecycleScope | Android Activity/Fragment | เมื่อ lifecycle ถูกทำลาย |
| coroutineScope | ภายในฟังก์ชัน suspend | เมื่อ parent job ถูกยกเลิก |
Job ปกติจะยกเลิก siblings ทั้งหมดเมื่อโครูทีนลูกตัวใดตัวหนึ่งล้มเหลว SupervisorJob เป็นข้อยกเว้น: ความล้มเหลวในโครูทีนลูกหนึ่งไม่ส่งผลกระทบต่อตัวอื่น ซึ่งสำคัญเมื่อมีงานอิสระหลายงานดำเนินการแบบขนาน และหนึ่งในนั้นอาจล้มเหลวโดยไม่จำเป็นต้องยกเลิกงานอื่น
Dispatchers กำหนดว่าโครูทีนจะทำงานบนเธรดใด Dispatchers.Main — เธรด UI หลักของ Android Dispatchers.IO — พูลสำหรับการดำเนินการที่บล็อก (เครือข่าย, ดิสก์) Dispatchers.Default — สำหรับงานที่ใช้ CPU มาก Dispatchers.Unconfined — เริ่มต้นในเธรดปัจจุบันแต่ไม่รับประกันว่าจะอยู่บนเธรดนั้น การเลือก Dispatcher ที่ถูกต้องสำคัญต่อประสิทธิภาพ: งาน IO บน Default จะบล็อกพูลคำนวณ ในขณะที่งาน CPU บน IO จะสร้างเธรดที่ไม่จำเป็น
withContext — ฟังก์ชันสำหรับเปลี่ยน Dispatcher ภายในโครูทีน ตัวอย่างเช่น ฟังก์ชัน suspend ที่แยกวิเคราะห์ JSON สามารถสลับไปที่ Dispatchers.Default สำหรับการคำนวณและกลับไปที่ Dispatchers.Main สำหรับการอัปเดต UI withContext เป็นตัวสร้างที่ใช้บ่อยที่สุดในการพัฒนา Android
launch — เริ่มโครูทีน คืนค่า Job ไม่คืนผลลัพธ์ (fire-and-forget) async — เริ่มโครูทีน คืนค่า Deferred ซึ่งสามารถรับผลลัพธ์ได้ผ่าน await runBlocking — บล็อกเธรดปัจจุบันเพื่อทำงานโครูทีน (เฉพาะสำหรับการทดสอบและฟังก์ชัน main) การเลือกตัวสร้าง ขึ้นอยู่กับสถานการณ์: launch เหมาะสำหรับเหตุการณ์และการอัปเดต async สำหรับงานที่มีผลลัพธ์ runBlocking เฉพาะสำหรับการทดสอบหรือจุดเริ่มต้น
ลองพิจารณาสามสถานการณ์เชิงปฏิบัติ: โครูทีนพื้นฐานกับ launch, การเรียกแบบขนานกับ async และการจัดการข้อผิดพลาดกับ SupervisorJob
viewModelScope.launch เริ่มโครูทีนในบริบท ViewModel เมื่อ ViewModel ถูกล้าง โครูทีนจะถูกยกเลิกโดยอัตโนมัติ
class ProfileViewModel : ViewModel() {
fun loadUser() {
viewModelScope.launch(Dispatchers.IO) {
val user = api.fetchUser()
withContext(Dispatchers.Main) {
showUser(user)
}
}
}
}
coroutineScope กับ async เริ่มสามคำขอแบบขนาน ผลลัพธ์จะถูกรวบรวมผ่าน .await() หากคำขอใดล้มเหลว คำขอทั้งหมดจะถูกยกเลิก
suspend fun loadDashboard(): Dashboard = coroutineScope {
val user = async { api.fetchUser() }
val posts = async { api.fetchPosts() }
val stats = async { api.fetchStats() }
Dashboard(user.await(), posts.await(), stats.await())
}
SupervisorJob ให้โครูทีนแต่ละตัวเสร็จสมบูรณ์อย่างอิสระ ข้อผิดพลาดในคำขอหนึ่งจะไม่ยกเลิกคำขออื่น
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
try { api.fetchUsers() } catch (e: Exception) { log(e) }
}
scope.launch {
try { api.fetchPosts() } catch (e: Exception) { log(e) }
}
เธรด (Thread) เป็นพื้นฐานของระบบปฏิบัติการ แต่ละเธรดมีสแต็กของตัวเอง (~1 MB) และต้องใช้การเรียกของระบบเพื่อสร้างและสลับ โครูทีน เป็นพื้นฐานของภาษา ไม่ผูกติดกับระบบปฏิบัติการ ใช้ Continuation เพื่อบันทึกสถานะและสลับที่ระดับ runtime โดยไม่ต้องเรียกของระบบ
ตามข้อมูลของ Google (2025) การใช้โครูทีนแทนเธรดช่วยลดการใช้หน่วยความจำสำหรับงานเบื้องหลังในแอปพลิเคชัน Android ลง 90–95% ไลบรารี Android สมัยใหม่ทั้งหมด (Retrofit, Room, WorkManager) มีการสนับสนุนโครูทีนในตัวผ่านฟังก์ชัน suspend Ktor (เฟรมเวิร์กไคลเอนต์ HTTP ของ JetBrains) ก็สร้างบนโครูทีนทั้งหมด โดยให้ฟังก์ชัน suspend สำหรับทุกคำขอโดยไม่มี API แบบ callback Room รองรับโครูทีนผ่านฟังก์ชัน suspend ใน DAO ซึ่งช่วยให้ดำเนินการค้นหาฐานข้อมูลโดยไม่บล็อกเธรดหลัก
เธรดยังคงจำเป็นสำหรับ โค้ดเนทีฟ ผ่าน JNI, การเรียกที่บล็อกซึ่งใช้ CPU มากโดยไม่จำกัดเวลา (การเรนเดอร์วิดีโอ, การจำลอง) และเมื่อรวมกับไลบรารี C สำหรับสิ่งอื่นทั้งหมด — โครูทีน
คำถามที่พบบ่อย
โครูทีน คือหน่วยงานที่สามารถระงับได้ซึ่งทำงานบนเธรดที่มีอยู่ เธรดคือทรัพยากรของระบบที่มีสแต็กของตัวเอง โครูทีนเบากว่าเธรดหลายพันเท่าและไม่บล็อกทรัพยากรเมื่อถูกระงับ
Dispatchers.IO ออกแบบมาสำหรับการดำเนินการ I/O ที่บล็อก (เครือข่าย, ไฟล์) และสามารถสร้างเธรดใหม่เมื่อจำเป็น Dispatchers.Default มีพูลขนาดคงที่ (จำนวนคอร์ CPU) สำหรับการคำนวณที่ใช้ CPU มาก
Job.cancel() ยกเลิกโครูทีนและลูกทั้งหมด หากต้องการตรวจสอบการยกเลิกภายในโครูทีน ให้ใช้ ensureActive() — มันจะโยน CancellationException ถ้าโครูทีนถูกยกเลิก
ได้ — ผ่านไลบรารี kotlinx-coroutines-rx3 ซึ่งมีฟังก์ชัน awaitSingle, awaitFirst และอื่น ๆ สำหรับแปลง Observable/Single เป็นฟังก์ชัน suspend และกลับผ่าน flowable
Flow คือสตรีมข้อมูลอะซิงโครนัสแบบเย็น ซึ่งเทียบเท่ากับ RxJava Observable ในโครูทีน Flow ปล่อยค่าตามลำดับและเสร็จสมบูรณ์ด้วยข้อยกเว้นหรือความสำเร็จ รองรับ map, filter, catch และตัวดำเนินการอื่น ๆ
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม