为什么 Executor.asCoroutineDispatcher 不像 newFixedThreadPoolContext 那样工作?

Why doesn't Executor.asCoroutineDispatcher work like newFixedThreadPoolContext?

我认为这两行在执行方面是等效的:

val context1 = Executors.newFixedThreadPool(2).asCoroutineDispatcher()
val context2 = newFixedThreadPoolContext(2, "Fixed")

但是当我在下面的代码中使用 "context2" 时它按预期工作,但是 "context1" 就像一个线程。

val context1 = Executors.newFixedThreadPool(2).asCoroutineDispatcher()

repeat(4) {
    launch {
        withContext(context1) {
            Thread.sleep(2000)
        }
    }
}

context1.close()

预期:2个线程将并行执行。代码应在 4 秒内完成,因为 2 个线程休眠 2 秒然后重复。

实际:只有一个线程执行,"repeat"串行执行,需要8秒完成。

这是一个错误吗?

或者找到的这个文档是什么意思here

If you need a completely separate thread-pool with scheduling policy that is based on the standard JDK executors, use the following expression: Executors.newFixedThreadPool().asCoroutineDispatcher().

玩完完整代码示例后:

import kotlinx.coroutines.*
import java.util.concurrent.Executors

fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")


fun main() = runBlocking {
    val context1 = Executors.newFixedThreadPool(2).asCoroutineDispatcher()
    val context2 = newFixedThreadPoolContext(2, "Fixed")

    repeat(4) {
        launch {
            withContext(context1) {
                log("Start sleep $it")
                Thread.sleep(2000)
                log("Finished sleep $it")
            }
        }
    }

//    context1.close()
}

我发现问题出在 "context1.close()"。如果我注释掉 "context1.close()" 它可以正常工作。我的猜测是 "launch" 调用没有阻塞,因此 "context1.close()" 在 "withContext" 在其他线程上执行之前执行。我原以为这会导致错误,但它似乎只是使它成为一个线程。