You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中如何等待Job完成?解决join()无限阻塞主线程问题

解决Kotlin协程Job.join()无限阻塞的问题

你的代码中调用job.join()会无限阻塞,核心原因是:根Job不会随子协程完成自动结束。

ServerImpl中的job是根协程Job,通过launch启动的两个协程是它的子任务,但根Job的状态不会因为所有子Job完成而自动变为"完成"。job.join()会一直阻塞,直到该Job被主动标记为完成(调用job.complete())或取消(调用job.cancel()),所以你的主线程会无限等待。

解决方案

在所有子协程完成后,手动标记根Job为完成状态即可。可以通过收集子协程的Job实例,等待它们全部执行完毕后调用job.complete()。

修改后的完整代码

package example.threading

import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext

interface Server {
    fun start()
    fun stop()
}

class ServerImpl : Server, CoroutineScope {

    private val job = Job()

    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Default + job

    override fun start() {
        println("Starting server")

        // 保存两个子协程的Job实例
        val backgroundJob1 = launch {
            println("Running server work in thread: ${Thread.currentThread().name}")
            delay(2000)
            println("Server background thread 1 completed")
        }

        val backgroundJob2 = launch {
            println("Running additional server work in thread: ${Thread.currentThread().name}")
            delay(1500)
            println("Server background thread 2 completed")
        }

        // 等待所有子任务完成后,标记根Job为完成状态
        launch {
            backgroundJob1.join()
            backgroundJob2.join()
            job.complete()
        }
    }

    suspend fun joinOnJob() {
        job.join()
    }

    override fun stop() {
        println("Stopping server")
        job.cancel()
    }
}


fun main() = runBlocking {
    go()
}


private suspend fun go() {
    println("--------------------------------------------------------------------------------")
    println("Example where there server is aborted prior to finishing:")
    val server = ServerImpl()
    server.start()

    println("Waiting on job to finish")
    server.joinOnJob()

    println("Server done processing from main thread")
}

修改说明

  1. 在start()方法中保存两个launch返回的子Job实例
  2. 新增一个协程,等待两个子Job全部执行完成后,调用job.complete()标记根Job为完成状态
  3. 此时joinOnJob()中的job.join()会在根Job完成后正常返回,主线程得以继续执行后续逻辑

内容的提问来源于stack exchange,提问作者user7858768

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 21:56:58