ai

coroutines kotlin คือ

coroutines kotlin คือ

Coroutines Kotlin คืออะไร

coroutines kotlin คือ

Kotlin Coroutines เป็นฟีเจอร์สำหรับ asynchronous programming ใน Kotlin ที่ช่วยให้เขียน concurrent code ได้ง่ายและอ่านง่ายเหมือนเขียน sequential code ปกติ Coroutines เบากว่า threads มาก (สร้างได้เป็นล้านตัวโดยไม่กิน memory เยอะ) ใช้งานกว้างขวางใน Android development, backend (Ktor, Spring), และ multiplatform บทความนี้อธิบาย Coroutines ตั้งแต่พื้นฐานจนถึงขั้นสูง พร้อมตัวอย่าง code, patterns ที่ใช้บ่อย และเปรียบเทียบกับ threading แบบดั้งเดิม

Coroutines พื้นฐาน

# coroutines_basics.kt — Kotlin Coroutines basics

import kotlinx.coroutines.*



// 1. launch — Fire and forget

fun main() = runBlocking {

    println("Start: ")



    // launch สร้าง coroutine ใหม่ — ไม่ block

    val job = launch {

        delay(1000) // suspend function — ไม่ block thread

        println("Coroutine 1: ")

    }



    // async — return ค่าได้ (Deferred)

    val deferred = async {

        delay(500)

        println("Coroutine 2: ")

        42 // return value

    }



    println("Waiting...")

    val result = deferred.await() // รอผลลัพธ์

    println("Result: $result")

    job.join() // รอให้ job เสร็จ



    println("Done!")

}



// Output:

// Start: main

// Waiting...

// Coroutine 2: main

// Result: 42

// Coroutine 1: main

// Done!

Coroutine Builders & Scope

# builders.kt — Coroutine builders and scope

import kotlinx.coroutines.*



// === Coroutine Builders ===



// 1. runBlocking — Block current thread (ใช้ใน main/tests)

fun main() = runBlocking {

    // code ข้างในเป็น coroutine scope

}



// 2. launch — Fire and forget (Job)

fun launchExample() = runBlocking {

    val job: Job = launch {

        delay(100)

        println("launched!")

    }

    job.join()

}



// 3. async — Return value (Deferred<T>)

fun asyncExample() = runBlocking {

    val deferred: Deferred<Int> = async {

        delay(100)

        42

    }

    val result = deferred.await()

    println("Result: $result")

}



// 4. coroutineScope — Structured concurrency

suspend fun fetchData(): List<String> = coroutineScope {

    val users = async { fetchUsers() }    // parallel

    val posts = async { fetchPosts() }    // parallel

    users.await() + posts.await()         // wait both

}



// === Dispatchers ===

fun dispatcherExample() = runBlocking {

    // Default — CPU-intensive (thread pool = CPU cores)

    launch(Dispatchers.Default) {

        println("Default: ")

    }



    // IO — I/O operations (thread pool = 64 threads)

    launch(Dispatchers.IO) {

        println("IO: ")

    }



    // Main — UI thread (Android)

    // launch(Dispatchers.Main) { updateUI() }



    // Unconfined — starts in caller thread, resumes in any

    launch(Dispatchers.Unconfined) {

        println("Unconfined: ")

    }

}



// === Structured Concurrency ===

// Parent coroutine รอ children ทั้งหมดก่อนจบ

// ถ้า child fail → parent cancel children ที่เหลือ

suspend fun structuredExample() = coroutineScope {

    launch { task1() }

    launch { task2() }

    launch { task3() }

    // coroutineScope จะรอทั้ง 3 tasks จบก่อน return

}

Patterns ที่ใช้บ่อย

coroutines kotlin คือ
# patterns.kt — Common coroutine patterns

import kotlinx.coroutines.*

import kotlinx.coroutines.flow.*



// === Pattern 1: Parallel Decomposition ===

suspend fun fetchUserProfile(userId: String): UserProfile = coroutineScope {

    val user = async { userService.getUser(userId) }

    val posts = async { postService.getUserPosts(userId) }

    val followers = async { socialService.getFollowers(userId) }



    UserProfile(

        user = user.await(),

        posts = posts.await(),

        followers = followers.await()

    )

}



// === Pattern 2: Timeout ===

suspend fun fetchWithTimeout(): String {

    return withTimeoutOrNull(3000) { // 3 seconds timeout

        fetchSlowApi()

    } ?: "Timeout — ใช้ default value"

}



// === Pattern 3: Retry ===

suspend fun <T> retry(

    times: Int = 3,

    initialDelay: Long = 100,

    maxDelay: Long = 5000,

    factor: Double = 2.0,

    block: suspend () -> T

): T {

    var currentDelay = initialDelay

    repeat(times - 1) {

        try {

            return block()

        } catch (e: Exception) {

            println("Retry /$times after ms")

        }

        delay(currentDelay)

        currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay)

    }

    return block() // last attempt

}



// === Pattern 4: Flow (Reactive Streams) ===

fun numberFlow(): Flow<Int> = flow {

    for (i in 1..10) {

        delay(100)

        emit(i) // ส่งค่าทีละตัว

    }

}



suspend fun flowExample() {

    numberFlow()

        .filter { it % 2 == 0 }

        .map { it * it }

        .collect { println("Received: $it") }

}



// === Pattern 5: Channel (Producer-Consumer) ===

fun CoroutineScope.produceNumbers() = produce<Int> {

    for (i in 1..100) {

        send(i)

        delay(10)

    }

}



suspend fun channelExample() = coroutineScope {

    val channel = produceNumbers()

    repeat(5) {

        println("Received: ")

    }

    channel.cancel()

}

Android + Coroutines

# android_coroutines.kt — Coroutines in Android

import kotlinx.coroutines.*

import androidx.lifecycle.ViewModel

import androidx.lifecycle.viewModelScope



// === ViewModel + Coroutines ===

class UserViewModel : ViewModel() {

    private val userRepository = UserRepository()



    // viewModelScope — auto-cancel เมื่อ ViewModel ถูก destroy

    fun loadUser(userId: String) {

        viewModelScope.launch {

            try {

                _loading.value = true



                // IO dispatcher สำหรับ network/database

                val user = withContext(Dispatchers.IO) {

                    userRepository.getUser(userId)

                }



                // กลับมา Main thread อัตโนมัติ

                _user.value = user



            } catch (e: Exception) {

                _error.value = e.message

            } finally {

                _loading.value = false

            }

        }

    }



    // Parallel loading

    fun loadDashboard() {

        viewModelScope.launch {

            try {

                val profile = async(Dispatchers.IO) { userRepository.getProfile() }

                val notifications = async(Dispatchers.IO) { notificationRepo.getAll() }

                val feed = async(Dispatchers.IO) { feedRepo.getLatest() }



                _dashboard.value = Dashboard(

                    profile = profile.await(),

                    notifications = notifications.await(),

                    feed = feed.await()

                )

            } catch (e: Exception) {

                _error.value = "Failed to load dashboard"

            }

        }

    }

}



// === Repository Pattern ===

class UserRepository(private val api: UserApi, private val db: UserDao) {

    // Room + Retrofit + Coroutines

    suspend fun getUser(id: String): User {

        return try {

            val user = api.getUser(id) // Retrofit suspend function

            db.insertUser(user)        // Room suspend function

            user

        } catch (e: Exception) {

            db.getUser(id) ?: throw e  // Fallback to cache

        }

    }

}



// === Retrofit Suspend Function ===

interface UserApi {

    @GET("users/{id}")

    suspend fun getUser(@Path("id") id: String): User



    @GET("users")

    suspend fun getUsers(): List<User>

}

Coroutines vs Threads

# comparison.py — Coroutines vs Threads comparison

import json



class CoroutinesVsThreads:

    COMPARISON = {

        "memory": {

            "coroutines": "เบามาก — สร้าง 100,000 ตัวใช้ RAM ไม่กี่ MB",

            "threads": "หนัก — 1 thread ใช้ ~1MB stack, 100,000 threads = 100GB",

        },

        "creation": {

            "coroutines": "สร้างเร็วมาก — microseconds",

            "threads": "สร้างช้ากว่า — milliseconds",

        },

        "switching": {

            "coroutines": "Context switch เบา — ไม่ต้อง OS involvement",

            "threads": "Context switch หนัก — OS kernel involvement",

        },

        "cancellation": {

            "coroutines": "Cooperative cancellation — structured concurrency",

            "threads": "ยากที่จะ cancel safely — interrupt + cleanup",

        },

        "error_handling": {

            "coroutines": "Structured — parent catch child exceptions",

            "threads": "Manual — uncaught exception handler",

        },

        "debugging": {

            "coroutines": "ง่ายกว่า — sequential-looking code",

            "threads": "ยาก — race conditions, deadlocks",

        },

    }



    def show_comparison(self):

        print("=== Coroutines vs Threads ===\n")

        for key, comp in self.COMPARISON.items():

            print(f"[{key}]")

            print(f"  Coroutines: {comp['coroutines']}")

            print(f"  Threads:    {comp['threads']}")

            print()



    def benchmark(self):

        print("=== Benchmark: 100,000 tasks ===")

        print(f"  Coroutines: ~1 second, ~50 MB RAM")

        print(f"  Threads:    Impossible (OutOfMemoryError) or very slow with thread pool")

        print(f"  Virtual Threads (Java 21): ~2 seconds, ~200 MB RAM")

        print(f"\n  Winner: Kotlin Coroutines (lightweight + structured concurrency)")



comp = CoroutinesVsThreads()

comp.show_comparison()

comp.benchmark()

FAQ - คำถามที่พบบ่อย

Q: Coroutines คืออะไร ต่างจาก Thread อย่างไร?

A: Coroutines เป็น lightweight concurrency primitive — เบากว่า thread มาก (สร้างได้เป็นแสนตัว) Thread = OS-level, หนัก, 1MB/thread Coroutine = language-level, เบา, หลาย coroutines แชร์ thread เดียว ข้อดี: code อ่านง่ายเหมือน sequential, structured concurrency, cancellation ง่าย

เนื้อหาเกี่ยวข้อง — แนะนำให้อ่าน SOPS Encryption Developer Experience DX

Q: suspend function คืออะไร?

แนะนำเพิ่มเติม — บทวิเคราะห์จาก XM Signal

A: suspend function = function ที่สามารถ "หยุดชั่วคราว" (suspend) แล้ว resume ทีหลังได้ โดยไม่ block thread ใช้ keyword "suspend" นำหน้า เรียกได้เฉพาะใน coroutine หรือ suspend function อื่น ตัวอย่าง: delay(), withContext(), network calls, database queries Compiler จะแปลง suspend function เป็น state machine อัตโนมัติ

เนื้อหาเกี่ยวข้อง — บทความที่เกี่ยวข้อง: TensorFlow Serving Agile Scrum Kanban

Q: Dispatcher ไหนใช้เมื่อไหร่?

A: Dispatchers.Main: อัปเดต UI (Android) Dispatchers.IO: Network, File I/O, Database (thread pool ใหญ่) Dispatchers.Default: CPU-intensive (calculation, sorting, parsing) Dispatchers.Unconfined: Testing, ไม่ค่อยใช้ใน production กฎ: ใช้ withContext() เปลี่ยน dispatcher — อย่า launch ใน wrong dispatcher

แนะนำเพิ่มเติม — หนังสือเทรดที่ SiamCafeBook

เนื้อหาเกี่ยวข้อง — บทความที่เกี่ยวข้อง: WordPress Block Theme Disaster Recovery Plan

Q: Flow คืออะไร ต่างจาก LiveData?

A: Flow = cold reactive stream — ส่งค่าหลายตัวตามลำดับ (เหมือน RxJava Observable) LiveData = lifecycle-aware observable — ใช้เฉพาะ Android UI Flow ดีกว่า: operators เยอะกว่า (map, filter, combine), ใช้ได้ทุก layer LiveData ง่ายกว่า: lifecycle-aware อัตโนมัติ, เหมาะ UI layer แนะนำ: ใช้ Flow ทั้ง project → แปลงเป็น LiveData ที่ ViewModel ด้วย asLiveData()

เนื้อหาเกี่ยวข้อง — แนะนำให้อ่าน MLOps Pipeline GreenOps Sustainability

XM Legend · เทรดเดอร์ & ผู้สอน Forex 13 ปี

ผู้ก่อตั้ง SiamCafe ตั้งแต่ปี 1997 · เทรดเดอร์สาย Forex มากกว่า 13 ปี ได้รับการยกย่องเป็น XM Legend · แบ่งปันความรู้ Forex, ไอที, AI และการเทรด จากประสบการณ์จริงในตลาดจริง