การยกเลิกร่วมมือกัน: 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การยกเลิกร่วมมือกัน: isActive และ ensureActive
- withTimeout และ withTimeoutOrNull
- การเก็บกวาดด้วย finally และ NonCancellable
- การส่งต่อการยกเลิกในลำดับชั้น Coroutine