目录

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:

asContextElement:

创建一个协程上下文元素(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"

asCoroutineDispatcher:

将常规的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()

js asDeferred:

将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)

}

asExecutor:

将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)

js asPromise:

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.

}

async:

Kotlin 协程库提供的一个构建器,用于在协程中执行异步任务。它与 launch 不同,async 返回一个 Deferred 对象,该对象包含异步任务的结果 这个就不写示例了 上面示例有

js await:

毫无阻碍地等待承诺的完成。

awaitAll:

并发执行多个异步任务并等待它们全部完成。你可以使用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"

}

awaitCancellation:

在协程中挂起,直到协程被取消。当协程被取消时,该函数将抛出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

cancelAndJoin:

取消任务并挂起调用协程,直到取消的任务完成。示例

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()

}

cancelChildren:

取消指定协程的所有子协程 示例

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

CancellableContinuation:

提供对协程取消的更细粒度控制,在协程执行期间能够检查和响应取消操作。

StateisActiveisCompletedisCancelledActive (initial state)truefalsefalseResumed (final completed state)falsetruefalseCanceled (final completed state)falsetruetrue

+-----------+ 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()

}

}

CancellationException:

取消异常

CloseableCoroutineDispatcher:

继承至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:

CompletableDeferred 是 Kotlin 协程库中的一个类,用于表示异步操作的结果。它是 Deferred 的一个特殊实现,专注于没有返回值的异步操作(Completable Deferred,无返回值)。CompletableDeferred 有两个主要的函数:complete 和 await。

complete: 用于完成这个 CompletableDeferred,表示异步操作已经完成。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: 

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

completeWith: 

这个方法的作用是将将给定的 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)

}

CompletionHandler:

对于 Job.invokeOnCompletion 和 CancellableContinuation.invokeOnCancellation 的处理程序 安装的处理程序不应抛出任何异常。如果出现异常,它们将被捕获,封装成 CompletionHandlerException,并重新抛出,可能导致与无关的代码崩溃。传递给处理程序的 cause 的含义: 

当任务正常完成时,cause 为 null。当任务被正常取消时,cause 为 CancellationException。不应将其视为错误。特别是不应将其报告到错误日志中。否则,任务失败。

注意:这种类型是支持父子层次结构并允许实现等待 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:

所有协程调度程序实现扩展的基类

以下是 CoroutineDispatcher 的一些标准实现,它们由 kotlinx.coroutines 提供,并作为 Dispatchers 对象的属性:

Dispatchers.Default:用于所有标准构建器,如果它们的上下文中没有指定调度器或任何其他 ContinuationInterceptor。使用一个共享的后台线程池,适用于消耗 CPU 资源的计算密集型协程。Dispatchers.IO:使用一个共享的线程池,在需要时创建线程,设计用于处理 IO 密集型的阻塞操作(如文件 I/O 和阻塞的套接字 I/O)。Dispatchers.Unconfined:在当前调用帧中启动协程执行,直到第一个挂起点,在那时协程构建器函数返回。协程将在稍后由相应的挂起函数使用的任何线程中恢复,而不限制在特定的线程或线程池中。Unconfined 调度器通常不应该在代码中使用。私有线程池可以使用 newSingleThreadContext 和 newFixedThreadPoolContext 创建。任意的 java.util.concurrent.Executor 可以使用 asCoroutineDispatcher 扩展函数转换为调度器。

在 Android 中,你可以使用这些调度器来指定协程的执行上下文,以便它们在适当的线程或线程池中运行,从而更好地管理并发和异步操作。

CoroutineName:

提供了一种在协程上下文中携带协程名字信息的方式,使得在调试和日志输出时能够更容易地追踪协程的执行。

// 在主线程启动一个协程

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:

另一种创建 CoroutineScope 并使用此范围调用挂起块的方式。它设计用于并发分解工作。提供的范围从外部范围继承其 coroutineContext,但覆盖上下文的 Job。如果此范围内的任何子协程失败,则此范围失败,其余的所有子协程都会被取消。

suspend fun showSomeData() = coroutineScope {

val data = async(Dispatchers.IO) {

// ... 为主线程加载一些 UI 数据 ...

}

withContext(Dispatchers.Main) {

doSomeWork()

val result = data.await()

display(result)

}

}

CoroutineStart:

CoroutineStart 是 Kotlin 协程库中用于协程启动的枚举类,它定义了在协程构建器(如 launch、async 等)中用作 start 参数的选项。以下是这些选项的简要概述:

DEFAULT:默认选项,会根据协程的上下文立即安排协程执行。LAZY:懒启动选项,只有在需要的时候才启动协程。ATOMIC:原子启动选项,在不可取消的方式下,根据协程的上下文立即安排协程执行。UNDISPATCHED:无调度启动选项,会在当前线程中立即执行协程,直到遇到第一个挂起点。 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()

}

Deferred:

一种非阻塞的可取消 future。它是 Job 的子类,表示具有结果的任务。

fun main() = runBlocking {

// 创建一个 Deferred 对象

val deferred: Deferred = async {

delay(1000) // 模拟耗时操作

42 // 返回结果

}

// 在不阻塞线程的情况下等待 Deferred 完成,并获取结果

val result: Int = deferred.await()

println("Result: $result")

}

Result: 42

 delay:

提供的一个挂起函数,用于在协程中进行延迟操作,而不会阻塞线程。它有两个重载形式

suspend fun delay(timeMillis: Long)suspend fun delay(duration: Duration)

这两个函数都能够将协程挂起一段时间,然后再继续执行。它们的作用是为了模拟暂停,而不是直接阻塞线程。

runBlocking {

println("Start")

delay(Duration.ofSeconds(1)) // 挂起协程 1 秒

println("After delay")

}

 Dispatchers:

参考CoroutineDispatcher

 ensureActive:

确保当前协程仍然保持活跃状态,如果协程或作业不再活跃,它会抛出 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 值,从而提高代码的健壮性

ExperimentalCoroutinesApi:

标记仍处于实验的coroutines API中,这意味着相应声明的设计存在公开的问题,这些问题可能会(也可能不会)导致它们在将来发生变化。粗略地说,这些声明有可能在不久的将来被弃用,或者它们行为的语义可能会以某种方式改变,这可能会破坏一些代码。

GlobalScope:

全局作用域用于启动顶级协程,这些协程在整个应用程序生命周期内运行,不会过早取消。请在有限的情况下合理安全地使用。

@OptIn(DelicateCoroutinesApi::class)

GlobalScope.launch {

while (true) {

delay(1000)

println("GlobalScope run once")

}

}

handleCoroutineException:

介绍:为协程构建器的实现提供一个辅助函数,是为了防止异常丢失而设计的,是一种最后的手段。用于处理那些在协程中未捕获且不能通过正常方式(比如使用 try-catch)处理的异常。

runBlocking {

val exceptionHandler = CoroutineExceptionHandler { _, exception ->

println("Caught an exception: $exception")

}

// 在这里,我们故意抛出一个异常,但由于有异常处理器,异常将被捕获。

val job = launch(exceptionHandler) {

throw RuntimeException("Intentional exception")

}

job.join() // 等待作业完成

}

invoke:

扩展函数,其作用是在指定的 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

IO:

Dispatchers.IO 是一个专门设计用于将阻塞 I/O 任务卸载到共享线程池的协程调度器

默认情况下,IO 线程池大小为 64。Dispatchers.IO 具有独特的弹性特性。使用 CoroutineDispatcher.limitedParallelism 可以获取不受 Dispatchers.IO 并行性限制

isActive:

介绍:检查协程是否处于活动状态的属性

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

job:

是 Kotlin 协程中的一个关键概念,用于表示一个可以取消的、带有生命周期的任务

Cancellation(取消): Job 可以被取消,用于中断任务的执行。取消一个 Job 会导致它的所有子 Job 也被递归地取消。Hierarchy(层次结构): Job 可以组成父子关系的层次结构,其中父 Job 的取消会立即取消所有子 Job。状态管理: Job 有多个状态,包括 New、Active、Completing、Cancelling、Cancelled 和 Completed。这些状态反映了 Job 的生命周期。

StateisActiveisCompletedisCancelledNew (optional initial state)falsefalsefalseActive (default initial state)truefalsefalseCompleting (transient state)truefalsefalseCancelling (transient state)falsefalsetrueCancelled (final state)falsetruetrueCompleted (final state)falsetruefalseException Handling(异常处理): 通过 Job,你可以处理任务执行过程中的异常,区分正常取消和异常取消。Concurrency and synchronization(并发和同步): Job 及其派生接口的所有函数都是线程安全的,可以从并发的协程中安全地调用,无需外部同步。

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()

}

joinAll:

用于挂起当前协程,直到传递的所有 Job 完成为止。这是一个方便的方法,可以等待多个协程的完成,而不必在代码中使用 job.join() 多次。

挂起当前协程直到所有给定的 Job 完成 runBlocking {

val job1 = launch { /* 协程1的逻辑 */ }

val job2 = launch { /* 协程2的逻辑 */ }

val job3 = launch { /* 协程3的逻辑 */ }

joinAll(job1, job2, job3)

} 挂起当前协程直到集合中的所有 Job 完成 runBlocking {

val jobs = listOf(

launch { /* 协程1的逻辑 */ },

launch { /* 协程2的逻辑 */ },

launch { /* 协程3的逻辑 */ }

)

jobs.joinAll()

}

launch:

启动协程的一个函数

MainScope:

介绍:为UI组件创建主协同作用域我一般理解为Android的Activity协程作用域

class MyAndroidActivity {

private val scope = MainScope()

override fun onDestroy() {

super.onDestroy()

scope.cancel()

}

}

NonCancellable:

一个特殊的 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

plus:

扩展函数,它的作用是将指定的协程上下文(CoroutineContext)添加到当前协程作用域 (CoroutineScope) 中,并覆盖当前作用域上下文中的相应键。这是为了方便地创建一个新的协程作用域,其中包含了当前作用域的上下文以及额外添加的上下文。 比如上面“NonCancellable+Dispatchers.Default”

runBlocking:

运行一个新的协程阻碍当前线程,直到它完成。这个函数不应该在协程中使用。它旨在将常规的阻塞代码与以挂起方式编写的库连接起来,以便在main函数和测试中。

Runnable:

用于表示一个可以在异步环境中执行的任务。在 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!

SupervisorJob:

一种特殊类型的 Job,它用于创建协程的层级结构,其中子协程的失败不会影响其它子协程。这允许在协程的层级结构中灵活地处理失败。supervisor可以实施自定义策略来处理其子项的失败。注意:不管如何父线程要是崩了子协程一样也是活不了的

launch创建的子协程,可以通过上下文中的CoroutineExceptionHandler来处理。(实施自定义策略)async创建的子协程,可以通过Deferred.await对结果延迟值进行处理(也需要实施自定义策略不然结果返回一样崩) 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

supervisorScope:

快捷的创建上述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

suspendCancellableCoroutine:

一个用于支持协程挂起的函数。它的主要作用是允许你在协程中等待一个单次回调的结果,并将结果返回给调用方。它提供了对取消的支持,确保在协程取消时及时清理资源。

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

withContext:

在不同的协程上下文中执行挂起函数。它的作用是在指定的协程上下文中执行一个挂起函数块,并在该块执行完成后返回结果

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

withTimeout :

挂起函数并在设置超时时间,如果超过了指定的时间,将抛出 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!

withTimeoutOrNull :

在协程中设置超时。它的作用是在指定的时间内运行一个挂起的代码块,并在超时时返回 null,而不是抛出异常。 超时会导致代码块内正在执行的代码被取消,并且在代码块内部激活或下一次激活可取消的挂起函数时,会抛出 TimeoutCancellationException 异常

runBlocking {

val result = withTimeoutOrNull(3000) {

// 在此处执行可能耗时的操作

delay(5000) // 模拟一个长时间的操作

"Operation completed"

}

if (result != null) {

println("Success: $result")

} else {

println("Timeout occurred")

}

}

Timeout occurred

yield:

将当前协程的执行权交出,让同一调度器上的其他协程有机会执行。它是一种协作式多任务处理的机制,允许协程在不阻塞线程的情况下进行切换。

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

参考链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。