Java缓存线程池(newCachedThreadPool)和固定数量线程池(newFixedThreadPool)

java5相比之前的Java版本,在并发编程上,有了非常大的提高,加了很多类,提供了很多可用于并发编程的工具包和工具类。尤其为人们所称道的,就是Java自带的线程池。

 

   Java5线程池的介绍文章,可以说在网上比比皆是,我就不再重复了,只是简单提一下,线程池给并发程序带 来了几个好处:

 

    1、创建和销毁线程的开销

   2、保护系统资源,避免创建太多的线程导致系统崩溃

   3、简化编程模型

 

Java5自带的线程池( ThreadPool),用于并发系统的,主要有:

缓存线程池(newCachedThreadPool):每个任务过来后都会创建一个线程,任务结束后,线程缓存一段时间,下次任务过来后,如果有之前缓存的线程就无须再创建而是直接使用。

 

固定数量线程池(newFixedThreadPool):创建固定线程数量的线程池,如果任务数大于线程池中线程的数量,那么任务将等待。

 

其实,我们看Java的源代码,就会发现,上面两种线程池,都是调用Java的ThreadPoolExecutor来实现的。其构造函数如下:

 

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)

 

我们可以看到,实际上是需要制定核心线程数、最大线程数、存活时间和时间单位、选择的队列这些参数。

其中,核心线程数的概念至关重要,当有任务到来时,如果线程池中的线程数还不够核心线程数,则启动一个新的线程来运行任务(即便其它线程在空闲);如果线程池中的线程已经达到核心数,但未达到最大数,则任务放到队列中等待空闲的核心线程处理;除非队列满,不会启动新的线程。

 

从这里,我们再来看缓存线程池和固定数量线程池,非常简单能够看出,缓存线程池的核心数为1,最大数为1,队列长度是1;固定线程池核心数和最大数都是设定的数量。

 

因为Java提供了这两种线程池,所以一般情况下,我们可能都觉得不需要再写别的线程池实现了,直接用这两种吧。结果在产品开发的过程中,笔者就遇到了很大的一个坑,差点掉进去出不来。

 

当时是要开发一款高性能、高稳定性的C/S模式的服务器产品,Java5之后,使用线程池改进了任务派发的部分,当时以为这两种线程池都应该能够满足要求,就先采用固定数量线程池来试,结果发现如果服务器和客户端都采用长连接,固定数量线程池存在很大的设计上的bug。

 

例如任务线程池核心数100,最大数100,客户端也正好100个连接连上了服务器。因为长连接机制下,为了保证处理效率,流程是服务器端ServerSocket在accept之后,不停循环,接受到请求后处理,然后继续等待连接上的数据,直至接收到客户端断开的指令或服务器端超时。

 

如下图:



 

 

可以想象,如果这时候第101个连接连上了服务器,再没有新的连接,TCP连接正常,任务也被接受放到了队列里,那么这个任务就只能乖乖等在队列里等着超时,别的什么都做不了!除非改变上面流程图中的方式,线程不再这样循环,而是直接返回,这个连接上新的数据过来由另外的线程处理,等待线程池重新分配,但这样效率一定不如图中的方式好,否则没有什么好的办法。

 

对于一些使用场景复杂的服务器端,客户端长连接和短连接都可能有的这种场景,使用固定大小线程池,就必须考虑这个问题。或者牺牲效率,或者深入考虑长连线程带来的问题。

 

既然固定大小有问题,那就看看缓存线程池吧,麻烦更大了,如果服务器没有别的辅助控制,一下子涌入大量的客户连接,服务器一下子需要启动大量的线程,很有可能崩溃,这个也是无法接受的。

 

    从这里可以看到,Java自带的两种线程池,其实是各有各自的适用场景,对池中的任务,也都有自己的要求和限制,在适用这些基础设施来设计系统之前,首先应该对这些进行透彻的分析,不要等到出现bug才醒悟。上面提到的bug,因为没有清晰的错误信息,就非常不容易分析出来。

 

    如果你的服务器面临这么复杂多变的客户端,而且既要求效率上不能牺牲,又希望使用Java的线程基础设施,那么一定要在这里慎重再慎重。


转自:http://windshome.iteye.com/blog/1811225

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值