9.4 协程是轻量级的
直接运行下面的代码:
fun testThread() {
val jobs = List(100_1000) {
Thread({
Thread.sleep(1000L)
print(".")
})
}
jobs.forEach { it.start() }
jobs.forEach { it.join() }
}
我们应该会看到输出报错:
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:714)
at com.easy.kotlin.LightWeightCoroutinesDemo.testThread(LightWeightCoroutinesDemo.kt:30)
at com.easy.kotlin.LightWeightCoroutinesDemoKt.main(LightWeightCoroutinesDemo.kt:40)
...........................................................................................
我们这里直接启动了100,000个线程,并join到一起打印”.”, 不出意外的我们收到了 java.lang.OutOfMemoryError
。
这个异常问题本质原因是我们创建了太多的线程,而能创建的线程数是有限制的,导致了异常的发生。在Java中, 当我们创建一个线程的时候,虚拟机会在JVM内存创建一个Thread对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。 能创建的线程数的具体计算公式如下:
Number of Threads = (MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize)
其中,参数说明如下:
参数 | 说明 |
---|---|
MaxProcessMemory | 指的是一个进程的最大内存 |
JVMMemory | JVM内存 |
ReservedOsMemory | 保留的操作系统内存 |
ThreadStackSize | 线程栈的大小 |
我们通常在优化这种问题的时候,要么是采用减小thread stack的大小的方法,要么是采用减小heap或permgen初始分配的大小方法等方式来临时解决问题。
在协程中,情况完全就不一样了。我们看一下实现上面的逻辑的协程代码:
fun testLightWeightCoroutine() = runBlocking {
val jobs = List(100_000) {
// create a lot of coroutines and list their jobs
launch(CommonPool) {
delay(1000L)
print(".")
}
}
jobs.forEach { it.join() } // wait for all jobs to complete
}
运行上面的代码,我们将看到输出:
START: 21:22:28.913
.....................
.....................(100000个)
.....END: 21:22:30.956
上面的程序在2s左右的时间内正确执行完毕。
当前内容版权归 JackChan1999 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 JackChan1999 .