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") }
修改说明
- 在
start()方法中保存两个launch返回的子Job实例 - 新增一个协程,等待两个子Job全部执行完成后,调用
job.complete()标记根Job为完成状态 - 此时
joinOnJob()中的job.join()会在根Job完成后正常返回,主线程得以继续执行后续逻辑
内容的提问来源于stack exchange,提问作者user7858768
相关产品推荐
相关产品推荐

