协程的bug?


#1

class MainActivity : BaseActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
runBlocking {
“run”.e()
launch(Dispatchers.Main) {
“start”.e()
}
“end”.e()
}
}
}
完整代码就是这样,只走了run和end,然后主线程就卡死了,"".e()就是个打印日志而已


#2

不是协程的 bug,是你代码逻辑的问题

假设你现在在公司,到点下班了,你心里想,“等我到家了我就下班回家”,请问你今天还能下班吗? :thinking:


#3

“run”.e 这是哪儿定义的?

哦在外面没看仔细。。。忽略我


#4

@JvmOverloads
fun String?.e(tagName: String = “lllttte”) {
log(2, tagName, this)
}


#5

emmm,那也不太对吧,我这样也是正常的

ThreadPool.submitToSingleThreadPool {
“1 ${Thread.currentThread().name}”.e()
ThreadPool.submitToSingleThreadPool {
“2 ${Thread.currentThread().name}”.e()
}
}

打印:
1590738917.469 E/lllttte: 1 pool-1-thread-1
1590738917.470 E/lllttte: 2 pool-1-thread-1


#6

首先,Dispatchers.Main 在安卓环境里是 UI 线程,也就是主线程,而 onCreate 也是在主线程执行的,这俩是同一个线程

然后,runBlocking 启动了一个协程,并且会阻塞启动它的那个线程(此处为主线程),直到里面的协程执行完毕;而 launch(Dispatchers.Main) 又启动了一个子协程,并且希望调度在主线程

众所周知,父协程需要等待所有的子协程执行结束才会结束,因此在这里,runBlocking 需要等 launch 里面的代码执行完之后,才会结束阻塞

然而,此时的主线程正在被 runBlocking 阻塞住,因此 launch 里面的代码不可能在主线程得到调度

这就是我前面说,你今天没法下班的原因 :expressionless:


#7

本人没有任何安卓编程经验,如果说错了请见谅,你的代码转换成线程池的写法,相当于这样

fun main() {
    val executor = Executors.newSingleThreadExecutor()

    executor.submit {
        println("run")
        val future = executor.submit { println("start") }
        println("end")
        future.get()
    }
}

#9

说得没错


#10

谢谢解答,思路搞明白了


#11

runblocking 本身设计是为了阻塞主线程 ,多数是为了测试用。 launchlaunch(Dispatchers.Main) 这地你把上下文设置成主线程。会卡死主线程


京ICP备16022265号-2 Kotlin China 2017 - 2018