Kotlin Coroutines:等待多个线程完成

Posted

技术标签:

【中文标题】Kotlin Coroutines:等待多个线程完成【英文标题】:Kotlin Coroutines : Waiting for multiple threads to finish 【发布时间】:2019-07-18 03:32:42 【问题描述】:

所以第一次看协程,我想并行处理大量数据并等待它完成。我环顾四周,看到了 RunBlocking 和 Await 等,但不知道如何使用它。

目前为止

val jobs = mutableListOf<Job>()
jobs += GlobalScope.launch  processPages(urls, collection) 
jobs += GlobalScope.launch  processPages(urls, collection2) 
jobs += GlobalScope.launch  processPages(urls, collection3) 

然后我想知道/等待这些完成

【问题讨论】:

【参考方案1】:

可以使用以下方法。

fun myTask() 
    GlobalScope.launch 
        val task = listOf(
            async 

            ,
            async 

            
        )
        task.awaitAll()

    

【讨论】:

【参考方案2】:

您可以使用async builder 函数并行处理大量数据:

class Presenter 
    private var job: Job = Job()
    private var scope = CoroutineScope(Dispatchers.Main + job) // creating the scope to run the coroutine. It consists of Dispatchers.Main (coroutine will run in the Main context) and job to handle the cancellation of the coroutine.

    fun runInParallel() 
        scope.launch  // launch a coroutine
            // runs in parallel
            val deferredList = listOf(
                    scope.asyncIO  processPages(urls, collection) ,
                    scope.asyncIO  processPages(urls, collection2) ,
                    scope.asyncIO  processPages(urls, collection3) 
            )

            deferredList.awaitAll() // wait for all data to be processed without blocking the UI thread

            // do some stuff after data has been processed, for example update UI
        
    

    private fun processPages(...) ...

    fun cancel() 
        job.cancel() // invoke it to cancel the job when you don't need it to execute. For example when UI changed and you don't need to process data
    

扩展函数asyncIO

fun <T> CoroutineScope.asyncIO(ioFun: () -> T) = async(Dispatchers.IO)  ioFun()  // CoroutineDispatcher - runs and schedules coroutines

GlobalScope.launch is not recommended to use 除非您希望协程在整个应用程序生命周期内运行并且不会提前取消。

编辑:正如 Roman Elizarov 所述,您可以尝试不使用 awaitAll() 函数,除非您想在处理完所有数据后立即更新 UI 或执行其他操作。

【讨论】:

不需要async,因为这里没有使用结果。也没有必要做awaitAll,因为无论如何外部协程都会等待所有的孩子。 我在线程 "main" java.lang.NoClassDefFoundError: kotlin/coroutines/jvm/internal/CoroutineImpl at java.lang.ClassLoader.defineClass1(Native Method) 中遇到异常 @Burf2000 我猜是因为使用了Dispatchers.Main。请查看指南以将其替换为适当的 Dispatcher github.com/Kotlin/kotlinx.coroutines/blob/master/ui/…。 我将其更改为默认值,确保我拥有最新的协程框架并且一切运行良好 其实这个不行,var processor = Processor() processor.runInParallel() println("finished") 立即打印出来【参考方案3】:

如果您使用结构化并发的概念,则无需手动跟踪当前的作业。假设您的 processPages 函数执行某种阻塞 IO,您可以将代码封装到以下挂起函数中,该函数在为此类工作设计的 IO 调度程序中执行您的代码:

suspend fun processAllPages() = withContext(Dispatchers.IO)  
    // withContext waits for all children coroutines 
    launch  processPages(urls, collection) 
    launch  processPages(urls, collection2) 
    launch  processPages(urls, collection3) 

现在,如果您的应用程序的最顶层函数还不是挂起函数,那么您可以使用runBlocking 调用processAllPages

runBlocking 
    processAllPages()

【讨论】:

这会并行运行所有作业吗? 我正在获取 suppend 函数 processAllPages() 只能从另一个协程或 suppsend 函数调用 @Burf2000 在 runBlocking 方法中调用 processAllPages()。

以上是关于Kotlin Coroutines:等待多个线程完成的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin协程基础介绍--协程(Coroutines)是一种轻量级的线程

Kotlin 协程源码解析

Kotlin 协程源码解析

Kotlin 协程源码解析

Kotlin 协程源码解析

使用 Kotlin Coroutines 更新我的 TextView 会导致它崩溃: