简单谈谈对kotlin协程的理解
Kotlin中的协程是什么
首先协程能做的,Java线程都能够做,Kotlin协程只是一套封装较好的Java线程api,她是“假协程”,非“真协程”。
为什么需要引入协程?
- 节省资源,轻量,无非就是
- 节省内存,每个线程都需要分配一段栈内存,以及其他一些资源。
- 节省分配线程的开销,创建和销毁都要进行系统调用
- 大量线程切换带来的开销
- 与nio配合实现非阻塞的编程,提高系统的吞吐、
- 使用起来更加顺畅,跑起来是异步的,写起来是同步的。
一条条来看,在 Web 服务中,Tomcat 线程数量一般在50-500,Spring默认给 200 个线程。假如每个线程128kb,500个线程才多大呢?可以忽略不计了吧。
再看分配线程的开销。Java线程池可以很好的解决问题,vertx、kotlin协程本质都是使用线程池实现的,又有多少开销呢?
再看切换线程的开销。线程的切换实际只会发生在活跃的线程上,在web场景中,大量的请求会因为io(发请求、db)挂起,根本不会参与操作系统的线程切换,为了减少线程切换的开销,真正要防范的是同时有大量活跃线程。
再说 nio。Java NIO/Netty/Vert.X/rxJava/Akka可以任意选择。一般来讲,Netty可以解决绝大部分因为IO的等待造成资源浪费的问题。
Java仅仅是没有解决“协程”在Java中的定义,以及“写得优雅“这个问题。
什么时候适合用协程
线程调度是被动调度,协程调度是主动调度。
在传统Java线程中,如果想要跑满CPU,在一些高并发,io密集型场景中,其效率不如协程。因为线程模型在遇到需要等待的地方时(如 io),并不会主动交出线程,需要创建更多线程来抢占CPU时间片,Java线程模型是1:1的,会创建大量操作系统级线程,并由操作系统进行管理调度,调度时机是随机的,频繁的调度会产生不小的开销。
而协程的调度是用户态进程内runtime管理的,这个过程没有操作系统的线程调度的干预,这就需要协程主动交出执行权,通常就是io。
如果是纯计算场景,程序中无需等待,线程又不是很多,那完全使用线程就足够了。