Kotlin协程的启动方式介绍

2022-09-09 15:57:36
目录
1.GlobalScope.launch2.runBlocking 启动协程3.async启动协程

启动协程的基本方式

1.GlobalScope.launch

代码示例:

fun testGlobalScope() {
    GlobalScope.launch {
        println("Coroutinue started!")
        delay(1000L)
        println("Hello World!")
    }
    println("After launch!")
    Thread.sleep(2000L)
    println("Process end!")
}
/**
 * After launch!
 * Coroutinue started!
 * Hello World!
 * Process end!
 */
@DelicateCoroutinesApi
public object GlobalScope : CoroutineScope {
    /**
     * Returns [EmptyCoroutineContext].
     */
    override val coroutineContext: CoroutineContext
        get() = EmptyCoroutineContext
}
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
}

launch函数是CoroutineScope的扩展函数,它有三个参数:

    context: CoroutineContext = EmptyCoroutineContext, 第一个参数是协程上下文,它的默认值是 EmptyCoroutineContext,如果不传这个参数,默认就会使用 EmptyCoroutineContext。也可以传入 Kotlin 官方为我们提供的 Dispatchers,来指定协程运行的线程池。(Dispatchers.IO、Dispatchers.Unconfined、Dispatchers.Main)start: CoroutineStart = CoroutineStart.DEFAULT,第二个参数是协程的启动模式,默认值是CoroutineStart.DEFAULT,CoroutineStart 是一个枚举类,一共有:DEFAULT、LAZY、ATOMIC、UNDISPATCHED。block: suspend CoroutineScope.() -> Unit,第三个参数是函数类型block,它的类型是suspend CoroutineScope.() -> Unit。本质是一个挂起函数。函数的返回值是一个 Job,它其实代表的是协程的句柄,并不能返回协程的执行结果。

    2.runBlocking>

    代码示例

    fun testRunBlocking2() {
        runBlocking {
            println("Coroutinue started!")
            delay(1000L)
            println("Hello World!")
        }
        println("After Launch")
        Thread.sleep(2000L)
        println("Process end")
    }
    /**
     * Coroutinue started!
     * Hello World!
     * After Launch
     * Process end
     */
    @Throws(InterruptedException::class)
    public actual fun <T> runBlocking(context: CoroutineContext, block: suspend CoroutineScope.() -> T): T {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        val currentThread = Thread.currentThread()
        val contextInterceptor = context[ContinuationInterceptor]
        val eventLoop: EventLoop?
        val newContext: CoroutineContext
        if (contextInterceptor == null) {
            // create or use private event loop if no dispatcher is specified
            eventLoop = ThreadLocalEventLoop.eventLoop
            newContext = GlobalScope.newCoroutineContext(context + eventLoop)
        } else {
            // See if context's interceptor is an event loop that we shall use (to support TestContext)
            // or take an existing thread-local event loop if present to avoid blocking it (but don't create one)
            eventLoop = (contextInterceptor as? EventLoop)?.takeIf { it.shouldBeProcessedFromContext() }
                ?: ThreadLocalEventLoop.currentOrNull()
            newContext = GlobalScope.newCoroutineContext(context)
        }
        val coroutine = BlockingCoroutine<T>(newContext, currentThread, eventLoop)
        coroutine.start(CoroutineStart.DEFAULT, coroutine, block)
        return coroutine.joinBlocking()
    }

    runBlocking是普通函数,第一个参数:context: CoroutineContext,协程上下文。第二个参数是函数类型,block: suspend CoroutineScope.() -> T,函数类型是有返回值类型 T 的,与 runBlocking 的返回值类型是一样的,runBlocking 其实是可以从协程当中返回执行结果的。

    fun testRunBlocking() {
        val runBlockingResult = runBlocking {
            delay(500L)
            return@runBlocking "HaHa"
        }
        println("result:$runBlockingResult")
    }
    result:HaHa

    runBlocking特点:

    runBlocking 启动的协程会阻塞当前线程的执行。

    3.async启动协程

    使用>

    代码示例

    fun testAsync() {
        runBlocking {
            val deferred = async {
                println("do async:${Thread.currentThread().name}")
                delay(1000L)
                return@async "do completed"
            }
            println("After async:${Thread.currentThread().name}")
            val result = deferred.await()
            println("Result is: $result")
        }
    }
    After async:main @coroutine#1
    do async:main @coroutine#2
    Result is: do completed
    public fun <T> CoroutineScope.async(
        context: CoroutineContext = EmptyCoroutineContext,
        start: CoroutineStart = CoroutineStart.DEFAULT,
        block: suspend CoroutineScope.() -> T
    ): Deferred<T> {
        val newContext = newCoroutineContext(context)
        val coroutine = if (start.isLazy)
            LazyDeferredCoroutine(newContext, block) else
            DeferredCoroutine<T>(newContext, active = true)
        coroutine.start(start, coroutine, block)
        return coroutine
    }

    async注意点

      async 启动协程以后,不会阻塞当前程序的执行流程。async{}的返回值,是一个 Deferred 对象,它的 await() 方法,就可以拿到协程的执行结果。await只是等待执行完,并不是触发执行。

      到此这篇关于Kotlin协程的启动方式介绍的文章就介绍到这了,更多相关Kotlin协程启动内容请搜索易采站长站以前的文章或继续浏览下面的相关文章希望大家以后多多支持易采站长站!