在jdk1.5的版本中,java提供了语言级别的线程池,对于需要使用线程池的业务系统和中间件框架等提供了方便的选择。我认为线程池主要有两个方面的作用:第一就是防止因为外部条件的变化,造成线程数的瞬间飙升,从而影响了正常的业务使用;第二就是提高线程的利用率,从而在性能上带来好处,例如在NIO模型中,工作线程池中只用了很少的线程,但却可以服务大量的连接。
demo源码:
网上有很多介绍线程池的文章,在这里我就不讲线程池的细节了,只围绕线程池的两个特性,用实际的案例来解释分析。之前我在工作中遇到过一个因为网络中断而引起的生产事故,整个jvm的资源都被都被业务线程耗光的情况。场景是这样的:在某些预约挂号业务里,客户发起了一笔挂号业务,需要把下单请求提交到医院的,在医院返回挂号成功后,才算一个业务的完结,但是由于生产环境的网络到某家医院的网络断了,最后就造成了因为一家医院的网络问题,整个服务的资源都被耗光的情况,服务直接停服了。
下面的两个demo模拟展示了因为线程在一定时间内不能释放,线程数急速增加,从而停服的情况:
demo Lesson7ThreadsOnly 模拟展示了因为一家医院的网络问题造成整个服务的线程数量飙升,并且服务停服的情况;
demo Lesson7ThreadPool 模拟展示了在使用线程池的情况下,就算某家医院因为网络问题使得它自己的线程池满负荷运行,但是却不会对其它医院的业务造成影响;
关于线程池提升性能,在不同的场景下提升的性能比率是不同的,以我下面的两个demo为例,因为核心业务执行的操作非常简单,所以性能的对比差异非常大,在1分钟内,使用纯线程的方式创建的订单数为:731560;而使用线程池的方式创建的订单数为:77674078,性能提升达到了100倍。
demo Lesson7ThreadsPerform 使用纯线程的方式进行下单操作,每笔订单都需要一个新线程来完成;
demo Lesson7ThreadPoolPerform 使用线程池的方式进行下单操作,每笔订单都只是被线程池中的某个线程作为一个任务来执行。
通过本文的4个demo像大家展示了线程池了两个主要功用:1是防止线程飙升,保护服务正常运行;2是提升性能。