挂起不是协程的特有的说法,操作系统层面会对任务调度过程中被中断后的状态叫做挂起。如果对挂起不理解,建议补充些操作系统的进程和线程调度的知识哈。
“在不阻塞的情况下,请求线程挂起等待请求结果,主线程继续执行。等结果回来返回到主线程。这个叫挂起?”
结果回来就是恢复执行了,挂起是前面半句描述的情况。
“视频和例子都存在挂起点执行后main方法执行完,导致协程耗时操作之后数据打印不出来。那这不是BUG吗?我用协程请求数据,然后数据回来我用不了?(这个问题是GlobalScope.launch。必须加Join,想要结果用GlobalScope.async)”
这不是bug,是因为main函数执行完以后,主线程结束,如果剩下的运行中的异步任务的线程是幽灵线程的话 Java 虚拟机就会直接退出。所以如果你希望在主线程里用到结果,那就 join 或者 await 一下。
delay 是个挂起函数,挂起后当前协程就不执行了,delay会在指定时间之后来恢复当前协程的执行,恢复的时候如果当前协程没有指定调度器,那么调度器就是默认调度器(背后是个线程池),那么当前线程会调度到这个线程池上执行,那么具体是哪个线程取决于当时的实际情况。图1和图2的结果其实没有什么本质区别,图2 delay 前后的日志在相同的线程打印出来其实表明delay后恢复时线程池恰好可以用这个线程来调度这个任务而已。
图3的情况跟前面不太一样,delay执行在 suspend fun main 当中,这个协程没有调度器,所以不会产生调度行为,而是直接运行在 delay 恢复的唤醒线程上。图4类似。
Job.start 是告诉 Job 可以开始执行了,Job.join 需要等待 Job 执行完才能继续执行,这两个里面一个逻辑上没有等待,一个逻辑上存在等待。这两个函数跟 Thread 的 start 和 join 的作用几乎一样,它的 start 同样立即返回,join 要阻塞当前线程(对应的协程的 join 就是挂起当前协程)。
协程本身是语言层面的东西,自然就基于了底层的操作系统、线程这样的概念,从同学的问题来看,对于线程池、线程、操作系统的一些概念的理解还需要继续加强哈,不然肯定会影响你对协程的理解的。