kotlin - Coroutine 协程
Posted 清浅岁月
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kotlin - Coroutine 协程相关的知识,希望对你有一定的参考价值。
kotlin - Coroutine 协程
协程的创建
kotlin 里没有 new ,自然也不像 JAVA 一样 new Thread,另外 kotlin 里面提供了大量的高阶函数,所以不难猜出协程这里 kotlin 也是有提供专用函数的。kotlin 中 GlobalScope 类提供了几个携程构造函数:
1.launch - 创建协程
2.async - 创建带返回值的协程,返回的是 Deferred 类
3.withContext - 不创建新的协程,在指定协程上运行代码块
4.runBlocking - 不是 GlobalScope 的 API,可以独立使用,区别是 runBlocking 里面的 delay 会阻塞线程,而 launch 创建的不会
kotlin 在 1.3 之后要求协程必须由 CoroutineScope 创建,CoroutineScope 不阻塞当前线程,在后台创建一个新协程,也可以指定协程调度器。比如 CoroutineScope.launch 可以看成 new Coroutine
GlobalScope.launch
// 创建一个新协程
delay(1000);// 不阻塞线程
async
// 创建一个新协程
withContext()// 指定一个协程
runBlocking
delay(1000); // 阻塞线程
第一种:
GlobalScope.launchde 的创建
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyStandaloneCoroutine(newContext, block) else
StandaloneCoroutine(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
三个参数:
CoroutineContext:
协程上下文,既协程运行的线程,可以使用Dispatchers指定,课可以 自定义使用线程池,Dispatchers也是CoroutineContext的子类,大概类似于android的content。Dispatchers可以指定四种:
Dispatchers.Default
Dispatchers.IO -
Dispatchers.Main - 主线程
Dispatchers.Unconfined - 没指定,就是在当前线程
// 自定义CoroutineContext 使用单线程池
val singleThreadContext = newSingleThreadContext("aa")
GlobalScope.launch(singleThreadContext)
CoroutineStart:
协程启动模式,英语基础好的直接看原文,更清楚直接。
DEAFAULT - 模式模式,不写就是默认,立即执行
/**
* Default -- immediately schedules the coroutine for execution according to its context.
*
* If the [CoroutineDispatcher] of the coroutine context returns `true` from [CoroutineDispatcher.isDispatchNeeded]
* function as most dispatchers do, then the coroutine code is dispatched for execution later, while the code that
* invoked the coroutine builder continues execution.
*
* Note that [Dispatchers.Unconfined] always returns `false` from its [CoroutineDispatcher.isDispatchNeeded]
* function, so starting a coroutine with [Dispatchers.Unconfined] by [DEFAULT] is the same as using [UNDISPATCHED].
*
* If coroutine [Job] is cancelled before it even had a chance to start executing, then it will not start its
* execution at all, but will complete with an exception.
*
* Cancellability of a coroutine at suspension points depends on the particular implementation details of
* suspending functions. Use [suspendCancellableCoroutine] to implement cancellable suspending functions.
*/
ATOMIC -立即安排执行,但是无法取消,和默认相似
/**
* Atomically (i.e., in a non-cancellable way) schedules the coroutine for execution according to its context.
* This is similar to [DEFAULT], but the coroutine cannot be cancelled before it starts executing.
*
* Cancellability of coroutine at suspension points depends on the particular implementation details of
* suspending functions as in [DEFAULT].
*/
UNDISPATCHED - 立即执行,直到遇到第一个暂停点,与ATOMIC不同点的是必须在同一个线程,这是一个实验性的api,后面 可能会发生变更。
/**
* Immediately executes the coroutine until its first suspension point _in the current thread_ as if the
* coroutine was started using [Dispatchers.Unconfined]. However, when the coroutine is resumed from suspension
* it is dispatched according to the [CoroutineDispatcher] in its context.
*
* This is similar to [ATOMIC] in the sense that coroutine starts executing even if it was already cancelled,
* but the difference is that it starts executing in the same thread.
*
* Cancellability of coroutine at suspension points depends on the particular implementation details of
* suspending functions as in [DEFAULT].
*
* **Note: This is an experimental api.** Execution semantics of coroutines may change in the future when this mode is used.
*/
LAZY - 在需要的时候自己启动
/**
* Starts the coroutine lazily, only when it is needed.
*
* See the documentation for the corresponding coroutine builders for details
* (like [launch][CoroutineScope.launch] and [async][CoroutineScope.async]).
*
* If coroutine [Job] is cancelled before it even had a chance to start executing, then it will not start its
* execution at all, but will complete with an exception.
*/
CoroutineScope:协程域
block - 闭包方法体,定义协程内需要执行的操作
Job - 协程构建函数的返回值,可以把 Job 看成协程对象本身,协程的操作方法都在 Job 身上了
job.start() - 启动协程,除了 lazy 模式,协程都不需要手动启动
job.join() - 等待协程执行完毕
job.cancel() - 取消一个协程
job.cancelAndJoin() - 等待协程执行完毕然后再取消
lunch与async
async执行可以带回参数,中的挂起只是阻塞当前这个执行的协程,不阻塞其他协程和线程
val deferred = GlobalScope.async
return@async "1111"
val ttr=deferred.await();
runBlocking
runBlocking 和 launch 区别的地方就是 runBlocking 的 delay 方法是可以阻塞当前的线程的,和Thread.sleep() 一样
以上是关于kotlin - Coroutine 协程的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin 协程单元测试错误:线程“main @coroutine#1 @coroutine#2”中的异常 java.lang.NullPointerException