Kotlin 协程协程取消 ① ( 协程作用域取消 | 协程作用域子协程取消 | 通过抛出异常取消协程 | Job#cancel 函数 | 自定义异常取消协程 )
Posted 韩曙亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin 协程协程取消 ① ( 协程作用域取消 | 协程作用域子协程取消 | 通过抛出异常取消协程 | Job#cancel 函数 | 自定义异常取消协程 )相关的知识,希望对你有一定的参考价值。
文章目录
一、协程取消
协程取消 :
- 取消协程作用域 : 取消 协程作用域 会将该作用域中的 所有 子协程 一同取消 ;
- 取消子协程 : 子协程 的取消 不会影响 同一层级的 兄弟协程的执行 ;
- 通过抛出异常取消协程 : 协程取消通常会通过 抛出 CancellationException 异常 实现 ;
- 挂起函数取消 : 定义在 kotlinx.coroutines 包下的 suspend 挂起函数 是可以取消的 , 如 delay 函数 ;
二、协程作用域取消
创建 协程作用域 CoroutineScope 实例对象 , 传入 调度器 :
// 创建协程作用域
val coroutineScope = CoroutineScope(Dispatchers.Default)
调用 协程作用域的 CoroutineScope#launch 方法 , 可以创建一个子协程 ;
val job0 = coroutineScope.launch
Log.i(TAG, "job0 子协程执行开始")
delay(2000)
Log.i(TAG, "job0 子协程执行完毕")
完整代码示例 :
- 首先 , 创建协程作用域 ;
- 然后 , 在协程作用域中 创建两个子协程 ;
- 最后 , 取消协程作用域 , 同时该作用域内的两个子协程也一并被取消了 ;
package kim.hsl.coroutine
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*
class MainActivity : AppCompatActivity()
val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
runBlocking
// 创建协程作用域
val coroutineScope = CoroutineScope(Dispatchers.Default)
val job0 = coroutineScope.launch
Log.i(TAG, "job0 子协程执行开始")
delay(2000)
Log.i(TAG, "job0 子协程执行完毕")
val job1 = coroutineScope.launch
Log.i(TAG, "job1 子协程执行开始")
delay(2000)
Log.i(TAG, "job1 子协程执行完毕")
// 100ms 后取消协程作用域
delay(100)
// 取消协程作用域
coroutineScope.cancel()
执行结果 : 取消 coroutineScope 协程作用域之后 , 该作用域下的 job0 和 job1 子协程都被取消了 , 两个子协程都没有执行完毕 ;
10:33:33.468 I job0 子协程执行开始
10:33:33.471 I job1 子协程执行开始
如果不取消协程作用域 , 应该打印如下内容 :
10:31:49.880 I job0 子协程执行开始
10:31:49.886 I job1 子协程执行开始
10:31:51.937 I job1 子协程执行完毕
10:31:51.938 I job0 子协程执行完毕
三、协程作用域子协程取消
单独取消 协程作用域 中的 子协程 , 协程作用域 中的其它 兄弟协程不受影响 ;
package kim.hsl.coroutine
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*
class MainActivity : AppCompatActivity()
val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
runBlocking
// 创建协程作用域
val coroutineScope = CoroutineScope(Dispatchers.Default)
val job0 = coroutineScope.launch
Log.i(TAG, "job0 子协程执行开始")
delay(2000)
Log.i(TAG, "job0 子协程执行完毕")
val job1 = coroutineScope.launch
Log.i(TAG, "job1 子协程执行开始")
delay(2000)
Log.i(TAG, "job1 子协程执行完毕")
// 100ms 后取消协程作用域
delay(100)
// 取消协程作用域中的子协程
job1.cancel()
执行结果 : 在 协程作用域 coroutineScope 中 启动了 job0 和 job1 两个协程 , 取消了 job1 协程 , job1 协程没有执行完毕 , job0 协程执行完毕 ;
四、通过抛出异常取消协程
1、Job#cancel 函数
调用 Job#cancel 函数 , 取消协程操作 , 该函数原型如下 :
/**
* 使用可选的取消[原因]取消此作业。
* 原因可用于指定错误消息或提供关于的其他详细信息
* 为调试目的而取消的原因。
* 有关取消机制的完整解释,请参阅[Job]文档。
*/
public fun cancel(cause: CancellationException? = null)
取消协程时 , 可以传入一个 CancellationException 异常实例对象 , 也可以不传 , 默认为 null ;
// 取消协程作用域中的子协程
job1.cancel()
也可以传入一个 自定义 CancellationException 类型的异常 , 取消协程 ;
// 取消协程作用域中的子协程
job1.cancel(CancellationException("自定义 CancellationException 异常"))
由于报出的 CancellationException 异常是正常情况 , 如果需要查看该异常 , 需要在协程中使用 try catch 代码块捕获该异常 ;
val job1 = coroutineScope.launch
try
Log.i(TAG, "job1 子协程执行开始")
delay(2000)
Log.i(TAG, "job1 子协程执行完毕")
catch (e: Exception)
Log.i(TAG, "job1 子协程执行捕获到异常 :")
e.printStackTrace()
2、默认异常取消协程
完整代码示例 :
package kim.hsl.coroutine
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*
class MainActivity : AppCompatActivity()
val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
runBlocking
// 创建协程作用域
val coroutineScope = CoroutineScope(Dispatchers.Default)
val job1 = coroutineScope.launch
try
Log.i(TAG, "job1 子协程执行开始")
delay(2000)
Log.i(TAG, "job1 子协程执行完毕")
catch (e: Exception)
Log.i(TAG, "job1 子协程执行捕获到异常 :")
e.printStackTrace()
// 100ms 后取消协程作用域
delay(100)
// 取消协程作用域中的子协程
job1.cancel()
执行结果 :
16:43:17.637 I job1 子协程执行开始
16:43:17.787 I job1 子协程执行捕获到异常 :
16:43:17.790 W kotlinx.coroutines.JobCancellationException: StandaloneCoroutine was cancelled; job=StandaloneCoroutineCancelling@bc6a601
3、自定义异常取消协程
传入自定义异常代码示例 :
package kim.hsl.coroutine
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.*
class MainActivity : AppCompatActivity()
val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
runBlocking
// 创建协程作用域
val coroutineScope = CoroutineScope(Dispatchers.Default)
val job1 = coroutineScope.launch
try
Log.i(TAG, "job1 子协程执行开始")
delay(2000)
Log.i(TAG, "job1 子协程执行完毕")
catch (e: Exception)
Log.i(TAG, "job1 子协程执行捕获到异常 :")
e.printStackTrace()
// 100ms 后取消协程作用域
delay(100)
// 取消协程作用域中的子协程
job1.cancel(CancellationException("自定义 CancellationException 异常"))
执行结果 :
17:20:56.487 I job1 子协程执行开始
17:20:56.629 I job1 子协程执行捕获到异常 :
17:20:56.630 W java.util.concurrent.CancellationException: 自定义 CancellationException 异常
17:20:56.631 W at kim.hsl.coroutine.MainActivity$onCreate$1.invokeSuspend(MainActivity.kt:33)
17:20:56.631 W at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
17:20:56.631 W at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:235)
17:20:56.631 W at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:167)
17:20:56.631 W at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:408)
17:20:56.631 W at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:442)
17:20:56.632 W at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:431)
17:20:56.632 W at kotlinx.coroutines.CancellableContinuationImpl.resumeUndispatched(CancellableContinuationImpl.kt:529)
17:20:56.632 W at kotlinx.coroutines.EventLoopImplBase$DelayedResumeTask.run(EventLoop.common.kt:497)
17:20:56.632 W at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:277)
17:20:56.632 W at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:87)
17:20:56.632 W at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:61)
17:20:56.633 W at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source:1)
17:20:56.633 W at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:40)
17:20:56.633 W at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source:1)
17:20:56.633 W at kim.hsl.coroutine.MainActivity.onCreate(MainActivity.kt:15)
17:20:56.633 W at android.app.Activity.performCreate(Activity.java:7144)
17:20:56.633 W at android.app.Activity.performCreate(Activity.java:7135)
17:20:56.634 W at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
17:20:56.634 W at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2931)
17:20:56.634 W at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3086)
17:20:56.634 W at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
17:20:56.634 W at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
17:20:56.634 W at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
17:20:56.635 W at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
17:20:56.635 W at android.os.Handler.dispatchMessage(Handler.java:106)
17:20:56.635 W at android.os.Looper.loop(Looper.java:193)
17:20:56.635 W at android.app.ActivityThread.main(ActivityThread.java:6718)
17:20:56.642 W at java.lang.reflect.Method.invoke(Native Method)
17:20:56.643 W at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
17:20:56.643 W at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
17:20:56.676 D Skia GL Pipeline
以上是关于Kotlin 协程协程取消 ① ( 协程作用域取消 | 协程作用域子协程取消 | 通过抛出异常取消协程 | Job#cancel 函数 | 自定义异常取消协程 )的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin 协程协程底层实现 ③ ( 结构化并发 | MainScope 作用域 | 取消协程作用域 | Activity 实现 CoroutineScope 协程作用域接口 )
Kotlin 协程协程底层实现 ③ ( 结构化并发 | MainScope 作用域 | 取消协程作用域 | Activity 实现 CoroutineScope 协程作用域接口 )
Kotlin 协程协程异常处理 ② ( SupervisorJob 协程 | supervisorScope 协程作用域构建器函数 )
Kotlin 协程协程异常处理 ② ( SupervisorJob 协程 | supervisorScope 协程作用域构建器函数 )