目录
asContextElement:
asCoroutineDispatcher:
js asDeferred:
asExecutor:
js asPromise:
async:
js await:
awaitAll:
awaitCancellation:
cancelAndJoin:
cancelChildren:
CancellableContinuation:
CancellationException:
CloseableCoroutineDispatcher:
CompletableDeferred:
CompletableJob:
completeWith:
CompletionHandler:
CoroutineDispatcher:
CoroutineName:
coroutineScope:
CoroutineStart:
Deferred:
delay:
Dispatchers:
ensureActive:
ensurePresent :
ExperimentalCoroutinesApi:
GlobalScope:
handleCoroutineException:
invoke:
IO:
isActive:
job:
joinAll:
launch:
MainScope:
NonCancellable:
plus:
runBlocking:
Runnable:
SupervisorJob:
supervisorScope:
suspendCancellableCoroutine:
withContext:
withTimeout :
withTimeoutOrNull :
yield:
创建一个协程上下文元素(CoroutineContext.Element)
,该元素可以被添加到协程上下文中,以便在特定的协程中检索和使用
注意:上下文元素不跟踪线程局部变量的修改
示例
val myThreadLocal = ThreadLocal()
println(myThreadLocal.get()) // 打印"null"
GlobalScope.launch(Dispatchers.Default + myThreadLocal.asContextElement(value = "foo")) {
println(myThreadLocal.get()) // 打印“foo”
withContext(Dispatchers.Main) {
println(myThreadLocal.get()) // UI线程上 打印“foo”
}
}
println(myThreadLocal.get())// 打印"null"
将常规的java.util.concurrent.Executor
转换为 Kotlin 协程中的 CoroutineDispatcher,
CoroutineDispatcher
是协程中用于调度协程执行的抽象,它决定了协程运行在哪个线程或线程池中。
示例
// 创建一个固定大小的线程池
val executor = Executors.newFixedThreadPool(2)
// 将线程池转换为 CoroutineDispatcher
val dispatcher: CoroutineDispatcher = executor.asCoroutineDispatcher()
// 在指定的调度器上启动协程
runBlocking(dispatcher) {
launch {
println("Task 1 is running on ${Thread.currentThread().name}")
}
launch {
println("Task 2 is running on ${Thread.currentThread().name}")
}
}
// 关闭线程池
executor.shutdown()
将JavaScript中的Promise
对象转换为Deferred
类型
示例
runBlocking {
val deferredResult = async {
// 模拟一个异步操作
delay(1000)
// Async operation completed
}
// 将 Deferred 对象转换为 Deferred 类型
val convertedDeferred: Deferred = deferredResult.asDeferred()
// 等待异步操作完成
val result = convertedDeferred.await()
println(result)
}
将CoroutineDispatcher
转换为Executor
接口。这对于与使用Java的一些库和API集成时很有用,因为它们可能期望一个Executor
而不是CoroutineDispatcher
示例
val dispatcher: CoroutineDispatcher = Dispatchers.Default
// 使用asExecutor将CoroutineDispatcher转换为Executor
val executor: Executor = dispatcher.asExecutor()
// 然后可以将其用于与期望Executor的Java库或API进行交互
val runnable = Runnable {
println("Running on executor")
}
executor.execute(runnable)
Deferred
对象转换为JavaScript中的Promise
对象。主要用于与基于Promise的异步编程框架
示例
suspend fun performAsyncTask(): String {
// Simulate an asynchronous task
kotlinx.coroutines.delay(1000)
return "Task completed"
}
fun main() {
// Start an asynchronous task using async
val asyncTask = lifecycleScope.async {
performAsyncTask()
}
// Convert the async task to a Promise
val promise: Promise = asyncTask.asPromise()
// Handle the Promise in JavaScript-like style
promise.then(
onFulfilled = { result ->
console.log("Promise resolved: $result")
},
onRejected = { reason ->
console.error("Promise rejected: $reason")
}
)
// In a real application, you might want to wait for the Promise to complete
// before exiting the program. This is just a simple example.
}
Kotlin 协程库提供的一个构建器,用于在协程中执行异步任务。它与 launch
不同,async
返回一个 Deferred
对象,该对象包含异步任务的结果 这个就不写示例了 上面示例有
毫无阻碍地等待承诺的完成。
并发执行多个异步任务并等待它们全部完成。你可以使用async
启动这些任务,然后使用awaitAll
等待它们的完成。
示例
fun main() = runBlocking {
val deferred1 = async { fetchDataFromNetwork1() }
val deferred2 = async { fetchDataFromNetwork2() }
// 等待两个异步任务完成
val result = try {
awaitAll(deferred1, deferred2)
} catch (e: Exception) {
// 处理异常
}
// 得到结果
println(result)
}
private suspend fun fetchDataFromNetwork1(): String {
// 模拟从网络获取数据的异步操作
delay(1000)
return "Data from Network 1"
}
private suspend fun fetchDataFromNetwork2(): String {
// 模拟从网络获取数据的异步操作
delay(1500)
return "Data from Network 2"
}
在协程中挂起,直到协程被取消。当协程被取消时,该函数将抛出CancellationException
,而不是返回Nothing。
示例
fun main() = runBlocking {
val job = launch {
try {
// 执行一些耗时任务
repeat(1000) { i ->
println("Task is running: $i")
delay(500)
}
} finally {
println("Task is cancelled")
}
}
// 模拟一段时间后取消协程
delay(2500)
job.cancelAndJoin()
// 这里的协程将一直挂起,直到它被取消
awaitCancellation()
}
Task is running: 0
Task is running: 1
Task is running: 2
Task is running: 3
Task is running: 4
Task is cancelled
cancel:
取消操作
示例
fun main() = runBlocking {
val job = CoroutineScope(Dispatchers.Default).launch {
try {
// 在这里执行一些异步操作,例如网络请求或耗时计算
withContext(Dispatchers.IO) {
// 模拟一个耗时操作
delay(1000)
}
// 在异步操作完成后执行一些操作
println("Task completed successfully")
} catch (e: CancellationException) {
// 在取消时的处理
println("Task was cancelled")
}
}
//取消
job.cancel()
delay(5000)//防止跑完 还没打印Task was cancelled就停止了
}
Task was cancelled
取消任务并挂起调用协程,直到取消的任务完成。示例
fun main() = runBlocking {
val job = CoroutineScope(Dispatchers.IO).launch {
try {
// 模拟一个耗时的操作
repeat(100) { index ->
println("Coroutine is running: $index")
delay(100)
}
} finally {
// 协程完成或取消时执行的清理工作
println("Coroutine cleanup")
}
}
// 取消并等待协程完成
job.cancelAndJoin()
}
取消指定协程的所有子协程 示例
fun main() = runBlocking {
startAsyncTasks()
delay(1500)
stopAsyncTasks()
delay(10000)
}
private var parentJob: Job? = null
fun startAsyncTasks() {
// 创建一个父协程作业
parentJob = CoroutineScope(Dispatchers.IO).launch {
try {
// 启动多个子协程来执行异步任务
val job1 = async { fetchDataFromNetwork1() }
val job2 = async { fetchDataFromNetwork2() }
// 等待所有子协程完成
val awaitAll = awaitAll(job1, job2)
// 所有任务完成后的操作
// ...
println(awaitAll)
} catch (e: CancellationException) {
// 当父协程被取消时,会进入此块
// 可以在这里处理取消时的清理工作
// ...
println("Task was cancelled")
}
}
}
fun stopAsyncTasks() {
// 取消父协程的所有子协程
parentJob?.cancelChildren()
}
private suspend fun fetchDataFromNetwork1(): String {
// 模拟从网络获取数据的异步操作
delay(1000)
return "Data from Network 1"
}
private suspend fun fetchDataFromNetwork2(): String {
// 模拟从网络获取数据的异步操作
delay(3500)
return "Data from Network 2"
}
Task was cancelled
提供对协程取消的更细粒度控制,在协程执行期间能够检查和响应取消操作。
State | isActive | isCompleted | isCancelled |
---|---|---|---|
Active (initial state) | true |
false |
false |
Resumed (final completed state) | false |
true |
false |
Canceled (final completed state) | false |
true |
true |
+-----------+ resume +---------+
| Active | ----------> | Resumed |
+-----------+ +---------+
|
| cancel
V
+-----------+
| Cancelled |
+-----------+
示例
fun main() = runBlocking{
try {
val result = withTimeout(5000) {
// 模拟一个需要时间较长的操作
performLongRunningOperation()
}
// 操作成功完成
println("Operation result: $result")
} catch (e: TimeoutCancellationException) {
// 操作超时
println("Operation timed out")
}
}
// 模拟一个需要时间较长的操作
private suspend fun performLongRunningOperation(): String = suspendCancellableCoroutine { continuation ->
val job = GlobalScope.launch(Dispatchers.IO) {
// 模拟一个长时间运行的任务
delay(10000)
println("任务完成")
// 如果协程没有被取消,就恢复 continuation
if (continuation.isActive) {
println("isActive == ture")
continuation.resume("Operation completed successfully"){
println("resume ${it.message}")
}
}
}
// 注册一个取消回调,以便在协程被取消时取消这个任务
continuation.invokeOnCancellation {
println("invokeOnCancellation ${it?.message}")
job.cancel()
}
}
取消异常
继承至CoroutineDispatcher额外提供了一个关闭它的方法,导致拒绝任何新任务,并清除与当前调度程序关联的所有底层资源
示例
class CustomDispatcher : CloseableCoroutineDispatcher() {
// 自定义调度逻辑的实现
override fun dispatch(context: CoroutineContext, block: Runnable) {
// 在这里实现自定义的调度逻辑
executor.submit {
block.run()
}
}
//原子操作
private val closed = AtomicBoolean(false)
override val executor: ExecutorService
get() = Executors.newSingleThreadExecutor()
override fun close() {
if (closed.compareAndSet(false, true)) {
// 在这里执行关闭资源的逻辑
// 这个示例中简单地关闭线程池
executor.shutdown()
println("Closing resources...")
}
}
}
fun main() = runBlocking {
// 示例中使用自定义调度程序
val customDispatcher = CustomDispatcher()
customDispatcher.use { customDispatcher ->
// 使用 withContext 指定自定义调度器
withContext(customDispatcher) {
// 在自定义调度器上执行异步任务
println("Running on custom dispatcher - Thread: ${Thread.currentThread().name}")
}
}
}
CompletableDeferred 是 Kotlin 协程库中的一个类,用于表示异步操作的结果。它是 Deferred 的一个特殊实现,专注于没有返回值的异步操作(Completable Deferred,无返回值)。CompletableDeferred 有两个主要的函数:complete 和 await。
class MyAsyncTask {
// 使用 CompletableDeferred 作为异步任务的结果
private val completableDeferred = CompletableDeferred()
fun doAsyncTask() {
// 在后台启动一个协程执行异步任务
GlobalScope.launch {
// 模拟异步任务的耗时操作
simulateAsyncOperation()
// 异步任务完成时调用 complete
completableDeferred.complete(Unit)
}
}
suspend fun getResult() {
// 等待异步任务完成
completableDeferred.await()
// 这里可以在主线程中处理异步任务完成后的逻辑
}
private suspend fun simulateAsyncOperation() {
// 模拟异步操作的耗时
println("In the consumption of time.")
delay(3000)
println("Time-consuming completion.")
}
}
fun main() = runBlocking {
val myAsyncTask = MyAsyncTask()
// 启动异步任务
myAsyncTask.doAsyncTask()
// 等待异步任务完成
myAsyncTask.getResult()
println("Async task completed.")
}
In the consumption of time.
Time-consuming completion.
Async task completed.
CompletableJob 在 Job 的基础上添加了一些额外的功能,使得它更适合一些特定的使用场景。CompletableJob 允许你手动完成(complete 一个任务。在协程中,当你使用 launch、async 等构建器创建协程时,它们会返回一个 Job 对象。这个 Job 对象就是协程的引用,你可以使用这个引用来控制协程的生命周期。
// 创建一个 CompletableJob
val completableJob = Job()
// 创建一个 CoroutineScope,并关联上面的 CompletableJob
val coroutineScope = CoroutineScope(Dispatchers.Default + completableJob)
// 启动一个协程
val job = coroutineScope.launch {
// 协程的逻辑
delay(1000) // 模拟一些工作
//任务完成时手动完成 job
completableJob.complete()
// 任务完成后,可以执行一些操作
println("Coroutine completed")
}
// 可以添加监听器来处理任务完成的事件
completableJob.invokeOnCompletion {
println("Job completed")
// 可以在这里执行一些额外的操作
}
// 在主线程中等待协程完成
runBlocking {
//手动完成 job
job.join()
}
Coroutine completed
Job completed
这个方法的作用是将将给定的 Result
对象的结果结果(成功或失败)传递给 CompletableDeferred。completeWith 返回一个布尔值,表示操作是否成功。如果 CompletableDeferred 已经被完成过,那么这个方法将返回 false。
runBlocking{
val completableDeferred = CompletableDeferred()
// 在后台线程中模拟异步操作,并将结果传递给 CompletableDeferred
GlobalScope.launch(Dispatchers.IO) {
try {
// 模拟异步操作成功,并将结果传递给 CompletableDeferred
val result = Result.success("Operation completed successfully")
completableDeferred.completeWith(result)
} catch (e: Exception) {
// 模拟异步操作失败,并将异常传递给 CompletableDeferred
val result = Result.failure(e)
completableDeferred.completeWith(result)
}
}
// 等待异步操作的结果
val result = completableDeferred.await()
// 打印结果
println(result)
}
对于 Job.invokeOnCompletion 和 CancellableContinuation.invokeOnCancellation 的处理程序
安装的处理程序不应抛出任何异常。如果出现异常,它们将被捕获,封装成 CompletionHandlerException,并重新抛出,可能导致与无关的代码崩溃。传递给处理程序的 cause 的含义:
注意:这种类型是支持父子层次结构并允许实现等待 Job 状态的挂起函数的内部机制的一部分。此类型不应在一般应用程序代码中使用。CompletionHandler 的实现必须快速且无锁。
val job = GlobalScope.launch {
// 协程的代码
delay(1000)
throw RuntimeException("Async task failed")
println("Coroutine completed")
}
// 设置协程完成时的处理程序
job.invokeOnCompletion { cause ->
when (cause) {
null -> {
println("Job completed successfully")
}
is CancellationException -> {
println("Job was cancelled")
}
else -> {
println("Job failed with exception: $cause")
}
}
}
// 等待协程完成
runBlocking {
job.join()
}
Exception in thread "DefaultDispatcher-worker-1" java.lang.RuntimeException: Exception while trying to handle coroutine exception
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handlerException(CoroutineExceptionHandler.kt:38)
at kotlinx.coroutines.CoroutineExceptionHandlerImplKt.handleCoroutineExceptionImpl(CoroutineExceptionHandlerImpl.kt:52)
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handleCoroutineException(CoroutineExceptionHandler.kt:33)
at kotlinx.coroutines.StandaloneCoroutine.handleJobException(Builders.common.kt:196)
at kotlinx.coroutines.JobSupport.finalizeFinishingState(JobSupport.kt:229)
at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:906)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:863)
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:828)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:100)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Suppressed: java.lang.RuntimeException: Async task failed
at com.yang.myapplication.MainActivityKt$main$job$1.invokeSuspend(MainActivity.kt:65)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
... 5 more
Caused by: java.lang.NoClassDefFoundError: android/os/Build$VERSION
at kotlinx.coroutines.android.AndroidExceptionPreHandler.handleException(AndroidExceptionPreHandler.kt:47)
at kotlinx.coroutines.CoroutineExceptionHandlerImplKt.handleCoroutineExceptionImpl(CoroutineExceptionHandlerImpl.kt:48)
... 13 more
Caused by: java.lang.ClassNotFoundException: android.os.Build$VERSION
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
... 15 more
Exception in thread "DefaultDispatcher-worker-1" java.lang.RuntimeException: Async task failed
at com.yang.myapplication.MainActivityKt$main$job$1.invokeSuspend(MainActivity.kt:65)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@6cb2c53e, Dispatchers.Default]
Job failed with exception: java.lang.RuntimeException: Async task failed
所有协程调度程序实现扩展的基类
以下是 CoroutineDispatcher 的一些标准实现,它们由 kotlinx.coroutines 提供,并作为 Dispatchers 对象的属性:
在 Android 中,你可以使用这些调度器来指定协程的执行上下文,以便它们在适当的线程或线程池中运行,从而更好地管理并发和异步操作。
提供了一种在协程上下文中携带协程名字信息的方式,使得在调试和日志输出时能够更容易地追踪协程的执行。
// 在主线程启动一个协程
runBlocking {
// 在 IO 线程执行异步操作
val result = withContext(Dispatchers.IO) {
// 协程名字为 "IOOperation"
val operationName = CoroutineName("IOOperation")
// 在 IO 线程中携带协程名字
val result = withContext(operationName + Dispatchers.IO) {
// 执行一些耗时的 IO 操作
"Result from IO operation"
}
// 打印协程名字
println("Coroutine name: ${operationName.name}")
result
}
// 打印异步操作的结果
println("Result on Main thread: $result")
}
Coroutine name: IOOperation
Result on Main thread: Result from IO operation
另一种创建 CoroutineScope 并使用此范围调用挂起块的方式。它设计用于并发分解工作。提供的范围从外部范围继承其 coroutineContext,但覆盖上下文的 Job。如果此范围内的任何子协程失败,则此范围失败,其余的所有子协程都会被取消。
suspend fun showSomeData() = coroutineScope {
val data = async(Dispatchers.IO) {
// ... 为主线程加载一些 UI 数据 ...
}
withContext(Dispatchers.Main) {
doSomeWork()
val result = data.await()
display(result)
}
}
CoroutineStart 是 Kotlin 协程库中用于协程启动的枚举类,它定义了在协程构建器(如 launch、async 等)中用作 start 参数的选项。以下是这些选项的简要概述:
runBlocking {
// 示例:使用 DEFAULT 启动协程
val job = GlobalScope.launch(start = CoroutineStart.DEFAULT) {
println("Coroutine started")
delay(1000)
println("Coroutine completed")
}
job.join()
// 示例:使用 LAZY 启动协程
val lazyJob = GlobalScope.launch(start = CoroutineStart.LAZY) {
println("Lazy Coroutine started")
delay(1000)
println("Lazy Coroutine completed")
}
lazyJob.start() // 手动启动
lazyJob.join()
// 示例:使用 ATOMIC 启动协程
val atomicJob = GlobalScope.launch(start = CoroutineStart.ATOMIC) {
println("Atomic Coroutine started")
delay(1000)
println("Atomic Coroutine completed")
}
atomicJob.join()
// 示例:使用 UNDISPATCHED 启动协程
val undispatchedJob = GlobalScope.launch(start = CoroutineStart.UNDISPATCHED) {
println("Undispatched Coroutine started")
delay(1000)
println("Undispatched Coroutine completed")
}
undispatchedJob.join()
}
一种非阻塞的可取消 future。它是 Job 的子类,表示具有结果的任务。
fun main() = runBlocking {
// 创建一个 Deferred 对象
val deferred: Deferred = async {
delay(1000) // 模拟耗时操作
42 // 返回结果
}
// 在不阻塞线程的情况下等待 Deferred 完成,并获取结果
val result: Int = deferred.await()
println("Result: $result")
}
Result: 42
提供的一个挂起函数,用于在协程中进行延迟操作,而不会阻塞线程。它有两个重载形式
这两个函数都能够将协程挂起一段时间,然后再继续执行。它们的作用是为了模拟暂停,而不是直接阻塞线程。
runBlocking {
println("Start")
delay(Duration.ofSeconds(1)) // 挂起协程 1 秒
println("After delay")
}
参考CoroutineDispatcher
确保当前协程仍然保持活跃状态,如果协程或作业不再活跃,它会抛出 CancellationException 异常。该函数提供了更精确的异常,因此你可以在协程内捕获 CancellationException,以便更好地处理取消的情况。
runBlocking {
launch {
try {
// 模拟耗时操作
repeat(1000) {
// 确保协程仍处于活动状态
ensureActive()
// 一些工作
println("Working $it")
delay(100)
}
} catch (e: CancellationException) {
// 在协程被取消时执行的代码
println("Coroutine cancelled: ${e.message}")
}
}
// 等待一段时间,然后取消协程
delay(500)
coroutineContext.cancelChildren()
}
Working 0
Working 1
Working 2
Working 3
Working 4
Coroutine cancelled: StandaloneCoroutine was cancelled
ensurePresent
:用于检查当前协程上下文中是否包含指定的 ThreadLocal 实例。如果该 ThreadLocal 不存在于协程上下文中,ensurePresent 会抛出 IllegalStateException。这有助于避免在协程中使用过时的或无效的 ThreadLocal 值,从而提高代码的健壮性
标记仍处于实验的coroutines API中,这意味着相应声明的设计存在公开的问题,这些问题可能会(也可能不会)导致它们在将来发生变化。粗略地说,这些声明有可能在不久的将来被弃用,或者它们行为的语义可能会以某种方式改变,这可能会破坏一些代码。
全局作用域用于启动顶级协程,这些协程在整个应用程序生命周期内运行,不会过早取消。请在有限的情况下合理安全地使用。
@OptIn(DelicateCoroutinesApi::class)
GlobalScope.launch {
while (true) {
delay(1000)
println("GlobalScope run once")
}
}
介绍:为协程构建器的实现提供一个辅助函数,是为了防止异常丢失而设计的,是一种最后的手段。用于处理那些在协程中未捕获且不能通过正常方式(比如使用 try-catch)处理的异常。
runBlocking {
val exceptionHandler = CoroutineExceptionHandler { _, exception ->
println("Caught an exception: $exception")
}
// 在这里,我们故意抛出一个异常,但由于有异常处理器,异常将被捕获。
val job = launch(exceptionHandler) {
throw RuntimeException("Intentional exception")
}
job.join() // 等待作业完成
}
扩展函数,其作用是在指定的 CoroutineDispatcher 上调用给定的挂起块,并等待其完成,然后返回结果。
runBlocking {
// 在 IO 线程上执行 fetchDataFromNetwork
val networkData = Dispatchers.IO.invoke {
fetchDataFromNetwork()
}
// 在默认的调度器上执行 fetchDataFromDisk
val diskData = Dispatchers.Default.invoke {
fetchDataFromDisk()
}
//2000+3000 后打印
println("Network Data: $networkData")
println("Disk Data: $diskData")
}
Network Data: Data from network
Disk Data: Data from disk
Dispatchers.IO 是一个专门设计用于将阻塞 I/O 任务卸载到共享线程池的协程调度器
介绍:检查协程是否处于活动状态的属性
runBlocking {
val job = launch {
repeat(1000) { i ->
// 检查协程是否仍处于活动状态
if (!isActive) {
println("Cancelling due to isActive = false")
return@launch
}
println("I'm sleeping $i ...")
delay(500L)
}
}
delay(1300L) // 等待一段时间
// 取消协程
println("main: Cancelling the job!")
job.cancelAndJoin()
println("main: Quitting")
//coroutineContext.isActive表达式是的快捷方式get(Job)?.isActive ?: true
//while (coroutineContext.isActive) {
// do some computation
//}
}
I'm sleeping 0 ...
I'm sleeping 1 ...
I'm sleeping 2 ...
main: Cancelling the job!
main: Quitting
是 Kotlin 协程中的一个关键概念,用于表示一个可以取消的、带有生命周期的任务
State | isActive | isCompleted | isCancelled |
---|---|---|---|
New (optional initial state) | false |
false |
false |
Active (default initial state) | true |
false |
false |
Completing (transient state) | true |
false |
false |
Cancelling (transient state) | false |
false |
true |
Cancelled (final state) | false |
true |
true |
Completed (final state) | false |
true |
false |
val job: Job = GlobalScope.launch {
// 协程的执行逻辑
delay(1000)
println("Coroutine completed")
}
// 在这里,我们可以对协程进行取消
// job.cancel()
// 等待协程完成
runBlocking {
job.join()
}
val job: CompletableJob = Job()
GlobalScope.launch(job) {
// 协程的执行逻辑
delay(1000)
println("Coroutine completed")
}
// 在这里,我们可以对协程进行取消
// job.complete()
// 等待协程完成
runBlocking {
job.join()
}
用于挂起当前协程,直到传递的所有 Job 完成为止。这是一个方便的方法,可以等待多个协程的完成,而不必在代码中使用 job.join() 多次。
runBlocking {
val job1 = launch { /* 协程1的逻辑 */ }
val job2 = launch { /* 协程2的逻辑 */ }
val job3 = launch { /* 协程3的逻辑 */ }
joinAll(job1, job2, job3)
}
runBlocking {
val jobs = listOf(
launch { /* 协程1的逻辑 */ },
launch { /* 协程2的逻辑 */ },
launch { /* 协程3的逻辑 */ }
)
jobs.joinAll()
}
启动协程的一个函数
介绍:为UI组件创建主协同作用域我一般理解为Android的Activity协程作用域
class MyAndroidActivity {
private val scope = MainScope()
override fun onDestroy() {
super.onDestroy()
scope.cancel()
}
}
一个特殊的 Job 对象,用于创建一个非可取消的协程。它是为了在某些代码块中防止被取消而设计的,通常与 withContext 函数一起使用。
注意:NonCancellable 并不是为了用在 launch、async 等协程构建器中的。如果你使用
launch(NonCancellable) { ... }
不仅新启动的任务不会在父任务被取消时取消,整个父子关系也会被切断。父任务将不等待子任务完成,也不会在子任务出现崩溃时被取消。
fun main() = runBlocking {
val coroutineScope = CoroutineScope(Dispatchers.IO).launch {
withContext(NonCancellable+Dispatchers.Default) {
repeat(10){
delay(1000)
println("NonCancellable print $it")
}
}
}
coroutineScope.cancel()
//防止整个线程退出 测试用
delay(19000)
}
NonCancellable print 0
NonCancellable print 1
NonCancellable print 2
NonCancellable print 3
NonCancellable print 4
NonCancellable print 5
NonCancellable print 6
NonCancellable print 7
NonCancellable print 8
NonCancellable print 9
扩展函数,它的作用是将指定的协程上下文(CoroutineContext)添加到当前协程作用域 (CoroutineScope) 中,并覆盖当前作用域上下文中的相应键。这是为了方便地创建一个新的协程作用域,其中包含了当前作用域的上下文以及额外添加的上下文。
比如上面“NonCancellable+Dispatchers.Default”
运行一个新的协程阻碍当前线程,直到它完成。这个函数不应该在协程中使用。它旨在将常规的阻塞代码与以挂起方式编写的库连接起来,以便在main函数和测试中。
用于表示一个可以在异步环境中执行的任务。在 kotlinx.coroutines 中,这个接口被扩展,以支持协程调度
class MyRunnable : Runnable {
override fun run() {
println("Hello from Runnable!")
}
}
// 在协程中执行
fun main() = runBlocking {
val runnable = MyRunnable()
val dispatcher: CoroutineDispatcher = Dispatchers.Default
dispatcher.dispatch(coroutineContext,runnable)
}
Hello from Runnable!
一种特殊类型的 Job,它用于创建协程的层级结构,其中子协程的失败不会影响其它子协程。这允许在协程的层级结构中灵活地处理失败。supervisor可以实施自定义策略来处理其子项的失败。
注意:不管如何父线程要是崩了子协程一样也是活不了的
runBlocking{
val supervisor = SupervisorJob(coroutineContext.job) // 创建一个 SupervisorJob 作为子协程
val coroutineScope = CoroutineScope(supervisor) // 使用 supervisor 作为协程的 Job
coroutineScope.launch {
// 执行一些操作
delay(1000)
println("Hello from SupervisorJob launch")
throw RuntimeException("Child Coroutine 1 failed!")
}
coroutineScope.async {
// 执行一些异步操作
delay(1500)
println("Hello from SupervisorJob async")
}
CoroutineScope(supervisor).launch{
// 执行一些异步操作
delay(100)
println("Hello from launch1")
//throw RuntimeException("lead to Parent Coroutine 1 failed!")
delay(2000)
println("Hello from launch2")
}
}
//这玩意我放fun main 跑的时候居然一直在运行很奇怪
Hello from launch1
Hello from SupervisorJob launch
Exception in thread "DefaultDispatcher-worker-2" java.lang.RuntimeException: Exception while trying to handle coroutine exception
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handlerException(CoroutineExceptionHandler.kt:38)
at kotlinx.coroutines.CoroutineExceptionHandlerImplKt.handleCoroutineExceptionImpl(CoroutineExceptionHandlerImpl.kt:52)
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handleCoroutineException(CoroutineExceptionHandler.kt:33)
at kotlinx.coroutines.StandaloneCoroutine.handleJobException(Builders.common.kt:196)
at kotlinx.coroutines.JobSupport.finalizeFinishingState(JobSupport.kt:229)
at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:906)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:863)
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:828)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:100)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Suppressed: java.lang.RuntimeException: Child Coroutine 1 failed!
at com.yang.myapplication.MainActivityKt$main$1$1.invokeSuspend(MainActivity.kt:82)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
... 5 more
Caused by: java.lang.NoClassDefFoundError: android/os/Build$VERSION
at kotlinx.coroutines.android.AndroidExceptionPreHandler.handleException(AndroidExceptionPreHandler.kt:47)
at kotlinx.coroutines.CoroutineExceptionHandlerImplKt.handleCoroutineExceptionImpl(CoroutineExceptionHandlerImpl.kt:48)
... 13 more
Caused by: java.lang.ClassNotFoundException: android.os.Build$VERSION
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
... 15 more
Exception in thread "DefaultDispatcher-worker-2" java.lang.RuntimeException: Child Coroutine 1 failed!
at com.yang.myapplication.MainActivityKt$main$1$1.invokeSuspend(MainActivity.kt:82)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@3ca7b389, Dispatchers.Default]
Hello from SupervisorJob async
Hello from launch2
快捷的创建上述SupervisorJob
runBlocking{
supervisorScope {
launch {
delay(1000)
println("Hello from SupervisorJob launch")
throw RuntimeException("Child Coroutine 1 failed!")
}
async {
delay(1500)
println("Hello from SupervisorJob async")
}
launch {
delay(2000)
println("Hello from SupervisorJob launch")
}
}
launch{
delay(2500)
println("Hello from launch2")
coroutineContext.job.cancel()
}
}
Hello from SupervisorJob launch
Exception in thread "main" java.lang.RuntimeException: Exception while trying to handle coroutine exception
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handlerException(CoroutineExceptionHandler.kt:38)
at kotlinx.coroutines.CoroutineExceptionHandlerImplKt.handleCoroutineExceptionImpl(CoroutineExceptionHandlerImpl.kt:52)
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handleCoroutineException(CoroutineExceptionHandler.kt:33)
at kotlinx.coroutines.StandaloneCoroutine.handleJobException(Builders.common.kt:196)
at kotlinx.coroutines.JobSupport.finalizeFinishingState(JobSupport.kt:229)
at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:906)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:863)
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:828)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:100)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:234)
at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:166)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:431)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:420)
at kotlinx.coroutines.CancellableContinuationImpl.resumeUndispatched(CancellableContinuationImpl.kt:518)
at kotlinx.coroutines.EventLoopImplBase$DelayedResumeTask.run(EventLoop.common.kt:500)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at com.yang.myapplication.MainActivityKt.main(MainActivity.kt:74)
at com.yang.myapplication.MainActivityKt.main(MainActivity.kt)
Suppressed: java.lang.RuntimeException: Child Coroutine 1 failed!
at com.yang.myapplication.MainActivityKt$main$1$1$1.invokeSuspend(MainActivity.kt:79)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
... 15 more
Caused by: java.lang.NoClassDefFoundError: android/os/Build$VERSION
at kotlinx.coroutines.android.AndroidExceptionPreHandler.handleException(AndroidExceptionPreHandler.kt:47)
at kotlinx.coroutines.CoroutineExceptionHandlerImplKt.handleCoroutineExceptionImpl(CoroutineExceptionHandlerImpl.kt:48)
... 23 more
Caused by: java.lang.ClassNotFoundException: android.os.Build$VERSION
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
... 25 more
Exception in thread "main" java.lang.RuntimeException: Child Coroutine 1 failed!
at com.yang.myapplication.MainActivityKt$main$1$1$1.invokeSuspend(MainActivity.kt:79)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:234)
at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:166)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:431)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:420)
at kotlinx.coroutines.CancellableContinuationImpl.resumeUndispatched(CancellableContinuationImpl.kt:518)
at kotlinx.coroutines.EventLoopImplBase$DelayedResumeTask.run(EventLoop.common.kt:500)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at com.yang.myapplication.MainActivityKt.main(MainActivity.kt:74)
at com.yang.myapplication.MainActivityKt.main(MainActivity.kt)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@58701e8c, BlockingEventLoop@951461a]
Hello from SupervisorJob async
Hello from SupervisorJob launch
Hello from launch2
一个用于支持协程挂起的函数。它的主要作用是允许你在协程中等待一个单次回调的结果,并将结果返回给调用方。它提供了对取消的支持,确保在协程取消时及时清理资源。
val mockApi = MockApi()
suspend fun awaitCallback() = suspendCancellableCoroutine { continuation ->
val callback = object : Callback {
override fun onCompleted(value: String) {
println("onCompleted $value")
// 用回调提供的值恢复协程
continuation.resume(value)
}
override fun onApiError(cause: Throwable) {
// 用回调提供的异常恢复协程
continuation.resumeWithException(cause)
}
}
mockApi.register(callback)
continuation.invokeOnCancellation{
mockApi.unregister(callback)
}
}
class MockApi : Api {
private var callback: Callback? = null
override fun register(callback: Callback) {
this.callback = callback
}
override fun unregister(callback: Callback) {
// 在取消时注销回调
this.callback = null
}
fun triggerCallback(value: String) {
runBlocking {
delay(2000)
println("Send Completed")
callback?.onCompleted(value)
}
}
fun triggerError(cause: Throwable) {
runBlocking {
delay(2000)
println("Send ApiError")
callback?.onApiError(cause)
}
}
}
interface Api {
fun register(callback: Callback)
fun unregister(callback: Callback)
}
interface Callback {
fun onCompleted(value: String)
fun onApiError(cause: Throwable)
}
// 在协程中执行
fun main():Unit =runBlocking{
//开个子协程
launch {
try {
val result = awaitCallback()
println("Callback completed with result: $result")
} catch (e: Throwable) {
println("Callback failed with exception: $e")
}
//等待回调的结果返回完成 继续执行
println("Continue to perform the task ")
}
// 模拟成功的回调
mockApi.triggerCallback("Success!")
//mockApi.triggerError(Throwable("Error"))
}
Send Completed
onCompleted Success!
Callback completed with result: Success!
Continue to perform the task
在不同的协程上下文中执行挂起函数。它的作用是在指定的协程上下文中执行一个挂起函数块,并在该块执行完成后返回结果
suspend fun exampleFunction() = withContext(Dispatchers.IO) {
// 在 IO 线程中执行耗时操作,例如网络请求或文件 I/O
delay(1000) // 模拟耗时操作
return@withContext "Result from withContext"
}
fun main() = runBlocking {
val result = exampleFunction()
println(result)
}
Result from withContext
挂起函数并在设置超时时间,如果超过了指定的时间,将抛出 TimeoutCancellationException 异常。这有助于在异步操作中设置超时,防止长时间等待或阻塞。
suspend fun performAsyncTask(): String {
delay(3000) // 模拟一个耗时的异步任务
return "Task completed successfully!"
}
fun performBlockingTask(): String {
Thread.sleep(3000) // 模拟一个阻塞任务
return "Blocking task completed successfully!"
}
fun main() = runBlocking {
try {
val result = withTimeout(2000) {
performAsyncTask()
//performBlockingTask()
}
println(result)
} catch (e: TimeoutCancellationException) {
println("Task timed out!")
}
}
Task timed out!
//Blocking task completed successfully!
在协程中设置超时。它的作用是在指定的时间内运行一个挂起的代码块,并在超时时返回 null,而不是抛出异常。
超时会导致代码块内正在执行的代码被取消,并且在代码块内部激活或下一次激活可取消的挂起函数时,会抛出 TimeoutCancellationException 异常
runBlocking {
val result = withTimeoutOrNull(3000) {
// 在此处执行可能耗时的操作
delay(5000) // 模拟一个长时间的操作
"Operation completed"
}
if (result != null) {
println("Success: $result")
} else {
println("Timeout occurred")
}
}
Timeout occurred
将当前协程的执行权交出,让同一调度器上的其他协程有机会执行。它是一种协作式多任务处理的机制,允许协程在不阻塞线程的情况下进行切换。
suspend fun launchWorker() = CoroutineScope(Dispatchers.Default).launch{
repeat(10) {
println("Worker coroutine is working $it")
delay(50)
// 使用 yield 让出执行权
yield()
}
}
fun main() = runBlocking {
val job = launchWorker()
// 主协程做一些其他事情
repeat(5) {
println("Main coroutine is doing some work $it")
delay(100)
}
// 等待工作协程完成
job.cancel()
}
Main coroutine is doing some work 0
Worker coroutine is working 0
Worker coroutine is working 1
Main coroutine is doing some work 1
Worker coroutine is working 2
Worker coroutine is working 3
Main coroutine is doing some work 2
Worker coroutine is working 4
Worker coroutine is working 5
Main coroutine is doing some work 3
Worker coroutine is working 6
Main coroutine is doing some work 4
Worker coroutine is working 7
Worker coroutine is working 8
Worker coroutine is working 9