使用Kotlin协程进行多线程处理

3

我正在尝试使用Kotlin协程,以下是我的代码:

fun main(args: Array<String>) = runBlocking {
    val cores = Runtime.getRuntime().availableProcessors()
    println("number of cores: $cores")

    val jobs = List(10) {
        async(CommonPool) {
            delay(100)
            println("async #$it on thread ${Thread.currentThread().name}")
        }
    }
    jobs.forEach { it.join() }
}

这是我的输出:
number of cores: 4
async number:0 on thread ForkJoinPool.commonPool-worker-2
async number:2 on thread ForkJoinPool.commonPool-worker-3
async number:3 on thread ForkJoinPool.commonPool-worker-3
async number:4 on thread ForkJoinPool.commonPool-worker-3
async number:5 on thread ForkJoinPool.commonPool-worker-3
async number:1 on thread ForkJoinPool.commonPool-worker-1
async number:7 on thread ForkJoinPool.commonPool-worker-3
async number:6 on thread ForkJoinPool.commonPool-worker-2
async number:9 on thread ForkJoinPool.commonPool-worker-3
async number:8 on thread ForkJoinPool.commonPool-worker-1

根据Roman Elizarov在另一个有关协程的问题的答案,启动只是创建新协程,而CommonPool将协程分派到ForkJoinPool.commonPool(),后者确实使用多个线程,在本例中执行多个CPU。
根据Java 8 文档
“对于需要单独或自定义池的应用程序,可以使用给定的目标并行性级别构建ForkJoinPool;默认情况下,等于可用处理器的数量。”
为什么只使用了3个工作线程?即使我增加异步任务的数量到1000+,这些工作线程仍然是相同的3个。
我的配置: Mac / High Sierra带有双核CPU(具有超线程,因此有4个可见核心),Kotlin 1.2,kotlinx-coroutines-core:0.19.3和JVM 1.8。
2个回答

6

如果您查看CommonPool的实现,您会注意到它是在java.util.concurrent.ForkJoinPool或具有以下大小的线程池上运行:

(Runtime.getRuntime().availableProcessors() - 1).coerceAtLeast(1)

4 个可用处理器,这将导致 3,这也解释了为什么您看到了 3 个工作线程。

可以按照以下方式确定 ForkJoinPool 的大小(将是相同的):

ForkJoinPool.commonPool().parallelism

如果您使用的协程版本大于等于1.0,请查看这个答案

4

从协程 1.0 开始,代码会略有不同,因为现在 CommonPool 将被替换为 Dispatchers.Default

fun main(args: Array<String>) = runBlocking {
    val cores = Runtime.getRuntime().availableProcessors()
    println("number of cores: $cores")

    val jobs = List(10) {
        async(Dispatchers.Default) {
            delay(100)
            println("async #$it on thread ${Thread.currentThread().name}")
        }
    }
    jobs.forEach { it.join() }
}

此外,您现在将获得以下内容:
它由JVM上共享的线程池支持。默认情况下,此分发程序使用的最大线程数等于CPU核心数,但至少为两个。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接