0Pricing
Kotlin Academy · บทเรียน

การยกเลิกร่วมมือกัน: isActive และ ensureActive

ทำให้ coroutine ยกเลิกได้ด้วยการตรวจสอบ isActive และเรียก ensureActive

การยกเลิกร่วมมือกัน: isActive และ ensureActive เป็นบทเรียน Kotlin Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Kotlin Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดจึงต้องยกเลิกแบบร่วมมือกัน

คอร์รูทีนของ Kotlin ใช้ การยกเลิกแบบร่วมมือกัน: คอร์รูทีนที่ถูกยกเลิกจะหยุดก็ต่อเมื่อให้ความร่วมมือโดยตรวจสอบสถานะการยกเลิก ลูปที่ใช้ CPU ต่อเนื่องจะไม่หยุดจนกว่าจะมีการตรวจสอบ

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        var i = 0
        while (true) { i++ } // never checks — never cancels!
    }
    delay(100)
    job.cancel()
    println("cancel sent but loop kept running until process ended")
}

การตรวจสอบ isActive

isActive เป็นพร็อพเพอร์ตีบน CoroutineScope ที่คืนค่า false เมื่อมีการร้องขอให้ยกเลิกแล้ว การตรวจสอบพร็อพเพอร์ตีนี้ในลูปจะทำให้คอร์รูทีนให้ความร่วมมือ

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        var i = 0
        while (isActive) {
            i++
        }
        println("Loop exited after $i iterations")
    }
    delay(10)
    job.cancel()
    job.join()
}

ensureActive()

ensureActive() จะส่งข้อผิดพลาด CancellationException หากคอร์รูทีนถูกยกเลิก และสามารถใช้แทน if (!isActive) throw CancellationException() ได้ทันที

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try {
            repeat(1_000_000) {
                ensureActive()  // throws if cancelled
                // heavy computation here
            }
        } catch (e: CancellationException) {
            println("Cancelled at iteration")
            throw e
        }
    }
    delay(5)
    job.cancel()
    job.join()
}

yield() ในฐานะจุดร่วมมือ

yield() จะพักคอร์รูทีนชั่วครู่ ทำให้ตัวจัดตารางเวลาตรวจสอบการยกเลิกและเรียกใช้คอร์รูทีนอื่นได้

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        repeat(10) { i ->
            yield()  // cooperative cancellation point + gives up scheduler
            println("Step $i")
        }
    }
    delay(2)
    job.cancel()
    job.join()
    println("Done")
}

isActive เทียบกับ ensureActive

ใช้ isActive สำหรับตรรกะแบบมีเงื่อนไข (เช่น ออกจากลูปอย่างเรียบร้อย) ใช้ ensureActive() เมื่อต้องการส่งต่อการยกเลิกในรูปแบบข้อผิดพลาดทันที

import kotlinx.coroutines.*
fun main() = runBlocking {
    launch {
        repeat(100) { i ->
            if (!isActive) {
                println("Stopping at $i, cleaning up...")
                return@launch
            }
            // work
        }
    }.also { delay(5); it.cancel(); it.join() }
}

CancellationException เป็นกรณีพิเศษ

CancellationException จะไม่ถูกส่งต่อไปยังขอบเขตแม่ แต่ใช้สื่อว่าการยกเลิกเกิดขึ้นตามปกติ ห้ามกลืนข้อยกเว้นนี้โดยเด็ดขาด ต้องส่งต่อด้วยการโยนซ้ำหรือปล่อยให้มันแพร่ต่อไปเสมอ

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try {
            delay(1000)
        } catch (e: CancellationException) {
            println("Caught cancellation, rethrowing")
            throw e  // important!
        }
    }
    delay(50)
    job.cancel()
    job.join()
    println("Job state: ${job.isCancelled}")
}

การยกเลิกในงานที่ใช้ CPU เป็นหลัก

สำหรับงานที่ใช้ CPU เป็นหลัก ให้แทรก ensureActive() หรือ yield() ไว้ที่จุดตรวจสอบตามธรรมชาติ เพื่อให้สามารถยกเลิกได้อย่างทันท่วงที

import kotlinx.coroutines.*
suspend fun heavyCompute(n: Int): Long {
    var result = 0L
    for (i in 0..n) {
        ensureActive()
        result += i
    }
    return result
}
fun main() = runBlocking {
    val job = launch(Dispatchers.Default) {
        println(heavyCompute(1_000_000))
    }
    delay(10)
    job.cancel()
    job.join()
}

การใช้ isActive ในฟังก์ชันระงับแบบกำหนดเอง

คุณสามารถเข้าถึง isActive ภายในฟังก์ชันระงับใดก็ได้ผ่าน coroutineContext.isActive หรือใช้ currentCoroutineContext().isActive

import kotlinx.coroutines.*
suspend fun checkable() {
    while (currentCoroutineContext().isActive) {
        delay(10)
        println("tick")
    }
}
fun main() = runBlocking {
    val job = launch { checkable() }
    delay(35)
    job.cancel()
    job.join()
}

การยกเลิกพร้อมการล้างทรัพยากร

แม้จะใช้การยกเลิกแบบร่วมมือกัน ก็ยังสามารถล้างทรัพยากรในบล็อก finally ได้ โดยข้อยกเว้นจากการยกเลิกยังคงแพร่ผ่านบล็อกเหล่านั้น

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        try {
            repeat(100) { i ->
                ensureActive()
                delay(20)
                println("Working $i")
            }
        } finally {
            println("Cleanup done")
        }
    }
    delay(50)
    job.cancel()
    job.join()
}

การตรวจสอบเป็นระยะด้วย isActive

ลูปตรวจสอบเป็นระยะเหมาะอย่างยิ่งกับ isActive: ให้ตรวจสอบต่อไปจนกว่าโคโรทีนจะถูกยกเลิก

import kotlinx.coroutines.*
fun main() = runBlocking {
    val job = launch {
        while (isActive) {
            println("Polling...")
            delay(100)
        }
        println("Poller stopped")
    }
    delay(350)
    job.cancel()
    job.join()
}

ความแตกต่างจาก Thread.interrupted()

ต่างจากเธรดของ Java ตรงที่โคโรทีนของคอตลินไม่อาศัยแฟล็กการขัดจังหวะ แต่จำลองการยกเลิกผ่านข้อยกเว้นและสถานะของขอบเขต ทำให้สามารถประกอบการทำงานและจัดโครงสร้างได้

import kotlinx.coroutines.*
fun main() = runBlocking {
    // Kotlin way: cooperative via isActive / ensureActive
    launch {
        ensureActive()
        println("Kotlin coroutine: cancellation is explicit and structured")
    }
}

ตรวจสอบอย่างรวดเร็ว

ฟังก์ชันใดโยนข้อยกเว้นทันทีเมื่อโคโรทีนถูกยกเลิก

ทบทวน

การยกเลิกแบบร่วมมือต้องมีจุดตรวจสอบอย่างชัดเจน: isActive ใช้สำหรับออกตามเงื่อนไข ensureActive() ใช้โยนข้อยกเว้นทันที และ yield() ใช้ระงับการทำงานเพื่อคืนเธรด ห้ามกลืน CancellationException โดยเด็ดขาด

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

บทเรียน “การยกเลิกร่วมมือกัน: isActive และ ensureActive” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การยกเลิกร่วมมือกัน: isActive และ ensureActive” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Kotlin Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การยกเลิกร่วมมือกัน: isActive และ ensureActive”

ทำให้ coroutine ยกเลิกได้ด้วยการตรวจสอบ isActive และเรียก ensureActive คุณปฏิบัติ Kotlin Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Kotlin Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Kotlin Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “การยกเลิกร่วมมือกัน: isActive และ ensureActive” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Kotlin Academy นี้ได้ไหม

ได้ บทเรียน Kotlin Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การยกเลิกร่วมมือกัน: isActive และ ensureActive
  2. withTimeout และ withTimeoutOrNull
  3. การเก็บกวาดด้วย finally และ NonCancellable
  4. การส่งต่อการยกเลิกในลำดับชั้น Coroutine
← กลับไปที่ Kotlin Academy