44其他并发模型-协程:更轻量级的线程
Java语言里解决并发问题靠的是多线程,但线程是个重量级的对象,不能频繁创建、销毁,而且线程切换的成本也很高,为了解决这些问题,Java SDK提供了线程池。然而用好线程池并不容易,Java围绕线程池提供了很多工具类,这些工具类学起来也不容易。那有没有更好的解决方案呢?Java语言里目前还没有,但是其他语言里有,这个方案就是协程(Coroutine)。
Java语言里解决并发问题靠的是多线程,但线程是个重量级的对象,不能频繁创建、销毁,而且线程切换的成本也很高,为了解决这些问题,Java SDK提供了线程池。然而用好线程池并不容易,Java围绕线程池提供了很多工具类,这些工具类学起来也不容易。那有没有更好的解决方案呢?Java语言里目前还没有,但是其他语言里有,这个方案就是协程(Coroutine)。
很多同学反馈说,工作了挺长时间但是没有机会接触并发编程,实际上我们天天都在写并发程序,只不过并发相关的问题都被类似Tomcat这样的Web服务器以及MySQL这样的数据库解决了。尤其是数据库,在解决并发问题方面,可谓成绩斐然,它的事务机制非常简单易用,能甩Java里面的锁、原子类十条街。技术无边界,很显然要借鉴一下。
上学的时候,有门计算机专业课叫做面向对象编程,学这门课的时候有个问题困扰了我很久,按照面向对象编程的理论,对象之间通信需要依靠消息,而实际上,像C++、Java这些面向对象的语言,对象之间通信,依靠的是对象方法。对象方法和过程语言里的函数本质上没有区别,有入参、有出参,思维方式很相似,使用起来都很简单。那面向对象理论里的消息是否就等价于面向对象语言里的对象方法呢?很长一段时间里,我都以为对象方法是面向对象理论中消息的一种实现,直到接触到Actor模型,才明白消息压根不是这个实现法。
实际工作中,我们总会难免和数据库打交道;只要和数据库打交道,就免不了使用数据库连接池。业界知名的数据库连接池有不少,例如c3p0、DBCP、Tomcat JDBC Connection Pool、Druid等,不过最近最火的是HiKariCP。
HiKariCP号称是业界跑得最快的数据库连接池,这两年发展得顺风顺水,尤其是Springboot 2.0将其作为默认数据库连接池后,江湖一哥的地位已是毋庸置疑了。那它为什么那么快呢?今天咱们就重点聊聊这个话题。
我们在《20 | 并发容器:都有哪些“坑”需要我们填?》介绍过Java SDK提供了2个有界队列:ArrayBlockingQueue 和 LinkedBlockingQueue,它们都是基于ReentrantLock实现的,在高并发场景下,锁的效率并不高,那有没有更好的替代品呢?有,今天我们就介绍一种性能更高的有界队列:Disruptor。
Netty是一个高性能网络应用框架,应用非常普遍,目前在Java领域里,Netty基本上成为网络程序的标配了。Netty框架功能丰富,也非常复杂,今天我们主要分析Netty框架中的线程模型,而线程模型直接影响着网络程序的性能。
在介绍Netty的线程模型之前,我们首先需要把问题搞清楚,了解网络编程性能的瓶颈在哪里,然后再看Netty的线程模型是如何解决这个问题的。
从今天开始,我们就进入案例分析模块了。 这个模块我们将分析四个经典的开源框架,看看它们是如何处理并发问题的,通过这四个案例的学习,相信你会对如何解决并发问题有个更深入的认识。
多线程设计模式是前人解决并发问题的经验总结,当我们试图解决一个并发问题时,首选方案往往是使用匹配的设计模式,这样能避免走弯路。同时,由于大家都熟悉设计模式,所以使用设计模式还能提升方案和代码的可理解性。
在这个模块,我们总共介绍了9种常见的多线程设计模式。下面我们就对这9种设计模式做个分类和总结,同时也对前面各章的课后思考题做个答疑。
前面我们在《34 | Worker Thread模式:如何避免重复创建线程?》中讲到,Worker Thread模式类比的是工厂里车间工人的工作模式。但其实在现实世界,工厂里还有一种流水线的工作模式,类比到编程领域,就是生产者-消费者模式。
前面两篇文章我们讲述的内容,从纯技术的角度看,都是启动多线程去执行一个异步任务。既启动,那又该如何终止呢?今天咱们就从技术的角度聊聊如何优雅地终止线程,正所谓有始有终。