简单谈谈对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。

如果是纯计算场景,程序中无需等待,线程又不是很多,那完全使用线程就足够了。