Что происходит с сопрограммами при выходе из основного потока? - PullRequest
0 голосов
/ 06 сентября 2018

В Java при выходе из основного потока все пользовательские потоки (не-deamon-потоки) будут продолжать работать, пока они не завершат свою работу.

У меня есть простая программа, которая выводит на консоль счетчик от 1 до 5.

Java-версия:

fun main(args: Array<String>) {
    println("Main start")

    countWithThread()

    println("Main end")
}

fun countWithThread() {
    Thread(Runnable {
        for (i in 1..5) {
            println("${Thread.currentThread().name} count $i")
            Thread.sleep(10)
        }
    }).start()
}

Выход:

Main start
Main end
Thread-0 count 1
Thread-0 count 2
Thread-0 count 3
Thread-0 count 4
Thread-0 count 5

Process finished with exit code 0

Kotlin версия:

fun main(args: Array<String>) {
    println("Main start")

    countWithCoroutine()

    println("Main end")
}

fun countWithCoroutine() {
    launch(CommonPool) {
        for (i in 1..5) {
            println("${Thread.currentThread().name} count $i")
            delay(10)
        }
    }
}

Выход:

Main start
Main end

Process finished with exit code 0

Как видите, при выходе из основного потока код в сопрограмме больше не запускается. Кажется, Котлин прервал все сопрограммы под капотом.

Может кто-нибудь сказать мне, что именно происходит с сопрограммами при выходе из основного потока?

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Сопрограммы сами по себе не "работают" так, как это знала бы JVM. Они не что иное, как объекты в куче.

Однако контекст сопрограммы имеет право голоса, когда он позволит JVM завершить работу. Создайте свой собственный:

val threadPool = Executors.newFixedThreadPool(4)
val dispatcher = threadPool.asCoroutineDispatcher()

Теперь, если вы используете его вместо CommonPool:

launch(dispatcher) { ... }

вы обнаружите, что JVM вообще не умирает, даже когда все задачи выполнены. Он выйдет только тогда, когда вы явно скажете

threadPool.shutdown()

Обратите внимание, однако, что executor.shutdown() не ведет себя по отношению к сопрограммам так же, как по отношению к «классическим» задачам, которые вы передаете ему. Исполнитель будет гарантировать, что все представленные задачи будут выполнены перед завершением работы, но он не учитывает приостановленные сопрограммы.

0 голосов
/ 06 сентября 2018

Сопрограммы завершаются, когда основной поток завершает выполнение, а экземпляр процесса / JVM умирает, они похожи на потоки демона. См. этот раздел в официальном руководстве по сопрограммам для справки.

...