不讲八股,我们来聊一聊协程是啥

 

如果你是个GoLand开发者或者是是使用Kotlin开发安卓的小伙伴,想必对协程已经很熟悉了,但是很多Java的后端小伙伴们,对协程的理解还停留在背八股文的阶段,这也是我写这篇文章的初衷,希望对你能有所帮助。

协程是一种用户态的轻量级线程,也叫微线程或纤程。上面的说法比较八股文,我认为换种说法可能更好理解。协程其实就是一段可以切换的执行的程序,在一个线程上运行着多个协程,不同协程的切换是由你的程序调度的,因此每个协程的运行不能阻塞住线程,不然一个协程把运行其的线程给阻塞住的话,其他协程也就不能被运行了。

协程的切换比线程的切换代价更小,比较适合IO密集型的应用。这点其实和线程是一样的,IO密集型应用会有大量的时间花费在IO等待上,所以才有了多线程和线程池。对计算密集型应用只需要用少量线程就好,毕竟CPU都花在运算上了,多个线程间的线程切换开销就是多余的了。

使用协程是在IO密集型的应用中,能比使用线程获得更好的吞吐量。在使用Java企业应用的开发中,我们会经常用到线程池去处理并发,但这并不是一个很好的实践,只是受限于JDK长久以来都没有支持协程的一种妥协。以Tomcat为例,假设我们使用500个的线程池去处理用户请求,每个用户请求里面会发起一笔远程http调用,远程http调用的花费时间为1s,那么这个Tomcat的吞吐量会由于线程池大小的限制,吞吐量也就只能达到500qps了。在这个例子中,就有很多点值得我们去思考:

  1. 为什么要使用线程池,为什么不能把线程池设置的更大?首先线程的创建开销是比较大的,所以我们要池化去复用线程,线程池的线程设置太大会让更多的CPU时间花费在线程的上下文切换中,其次,操作系统对线程数也是有个上限的,不能无限制的去创建线程。
  2. 远程http调用花费了1s的时间,这个时候我们的线程在干嘛,我们的线程被这个同步IO给阻塞住了,啥也没干,就干等着。对于这点后面也就出现了异步非阻塞的http客户端,通过异步回调去处理请求返回后要运行的代码。
  3. 但是如果在回调中又出现了异步IO请求,就又有其回调,于是回调中嵌套着回调,大量的嵌套后,你就陷入了回调地狱。幸运的是我们有CompletableFuture做异步编排,解决了回调地狱的问题,让代码的可读性和可维护性更好了。但是别忘了,你就算做了异步编排,你这比请求还是运行在线程上的,你的线程还是要阻塞等待花费时间最长的那条调用链走完拿到结果,才能返回响应把线程让出来的。
  4. 看来我们要提高吞吐,从根本上就得把这个线程池给干掉了。大家想一想,我们能不能用一条线程去同时处理多个用户的请求请求,只要你的业务逻辑中不包含同步阻塞的IO把线程阻塞住完全是可行的。举个简单的例子,我们的业务逻辑:CPU计算1(时间忽略不计) + IO1(远程网络调用,耗时1s)+ CPU计算2(时间忽略不计) 。这时候同时来了两笔请求,第一笔请求先占用我们的线程执行CPU计算1,然后执行IO1,发出IO请求(时间也很短,只是写网络IO缓冲)后让出线程(不等待IO响应,登记回调,当IO响应后回调执行CPU计算2)。这时我们的第二笔请求就可以获得线程进行执行了,同样执行了CPU计算1和IO1,发出IO请求,然后让出线程。过了1s后,两笔请求的IO响应都回来了,我们的线程继续干活,分别执行请求1的CPU计算2和请求2的CPU计算2,然后两笔请求都返回了。这个时候我们再看看吞吐,神奇的事情发生了,我们只用了一个线程就实现了2qps的吞吐!如果同时来的请求是2000不是两笔呢,我们的吞吐在一个线程上达到了2000qps!
  5. 有了以上的铺垫,我们知道我们可以怎么样去提高IO密集型应用的吞吐了,我们就需要一种简单又容易理解的编程范式去编写我们的业务代码,毕竟异步回调的写法还是没有同步的写法来的简单和容易理解的。于是,协程来了,我们可以用类似创建创建线程的方式去创建协程,我们的又可以用同步的方式去写我们的业务逻辑了,什么异步回调的,统统交给协程自己去调度切换去处理吧。

协程的作用是提高程序的并发性能,节省内存空间,简化异步编程。简而言之,就是将异步回调的编程模型,改成类似线程的同步范式。近些年GoLand异军突起,抢走Java在企业服务端的份额,Go支持的协程可谓是功不可没。好消息是,JDK19已经开始支持协程了 ,下一篇文章我会给大家分享下,协程在Java中的4种使用方式。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值