【问题标题】:kotlin coroutines - why does Thread.sleep not pause main thread from with launch?kotlin coroutines - 为什么 Thread.sleep 不会在启动时暂停主线程?
【发布时间】:2020-07-24 14:58:34
【问题描述】:

我想尝试从一个courtine 中暂停主线程。几个问题,但首先让我向您展示我正在使用的代码块作为测试:

class MainActivity : Activity(), CoroutineScope by MainScope() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    launch(Dispatchers.Main) {

        val threadName = Thread.currentThread()
        Log.v("mytag", "$threadName")
        Log.v("mytag", "111 ")
        Thread.sleep(5000)
        Log.v("mytag", "222")

    }

    Thread.sleep(2500) //give coroutine some time to launch fully. 
    Log.v("mytag", "333")
}

}

产生以下输出:

V/mytag: 333
V/mytag: Thread[main,5,main]
V/mytag: 111 
V/mytag: 222

因为我打印出当前线程名称,它不是 main 吗?我得到“线程[main,5,main]”

所以假设我在主线程上,那么为什么当我运行 Thread.sleep(5000) 时会打印“333”?我希望“333”将是最后一次打印,因为我已经冻结了主线程。

【问题讨论】:

    标签: kotlin-coroutines


    【解决方案1】:

    调度程序Dispatchers.Main 安排协程在主线程被释放后立即运行。

    它不会立即启动,并且由于您的 onCreate() 也在主线程上运行,因此主线程一旦 onCreate() 就不是空闲的,主线程循环器将检查任何计划的协程并运行它如果有。

    如果您明确希望在调用启动后立即启动,并且如果您是线程的所有者(在本例中为 main)并且您是此处的所有者,因为您的函数 onCreate 在 main 上运行,您可以使用Dispatchers.Main.immediate那里的调度员。

    // immediate will launch immediately if current function is running on Dispatchers.Main which is true
    launch(Dispatchers.Main.immediate) {
        val threadName = Thread.currentThread()
        Log.v("mytag", "$threadName")
        Log.v("mytag", "111")
        Thread.sleep(5000)
        Log.v("mytag", "222")
    }
    
    Thread.sleep(2500)
    Log.v("mytag", "333")
    

    输出(日志):

    V/mytag: Thread[main,5,main]
    V/mytag: 111 
    V/mytag: 222
    V/mytag: 333
    

    【讨论】:

    • 就是这样。杰出的。 Dispatchers.Main.immediate 就是答案。谢谢。
    【解决方案2】:

    所以假设我在主线程上

    是的,我相信你在主线程上。协程基础设施可能会暂时重命名线程,以便您更好地诊断在该线程上运行的实际协程。

    那么为什么当我运行 Thread.sleep(5000) 时会打印“333”?我希望“333”将是最后一次打印,因为我已经冻结了主线程。

    您的launch 调用会创建一个新的协程并将其添加到主线程事件队列的尾部。然后它继续阻塞主线程 2.5 秒。之后,onCreate 回调可能最终完成,GUI 事件循环可能会继续处理来自事件队列的事件,并最终到达由您的 launch 调用添加到那里的事件,这将再次阻塞 GUI 线程 5 秒.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-27
      • 2013-02-10
      • 2022-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多