关注 Java 线程池的任务队列长度

 

Java 5.0 就开始自带线程池的实现,其中固定大小的线程池,对普通使用还是很好用的。就是 Executors.newFixedThreadPool ,指需要指定一个大小数目就可以。相对于其他几种方式,易于实现高效稳定的服务器。

 

但是好用归好用,一些需要非常细心的问题,还是需要关注的,尤其是高并发场景,7*24不间断运行场景下。本文就是把这些地方记录下来,在设计和实现时,在这些问题上务必不能马虎,因为这关系到稳定性和效率,且不易通过测试来排查。

 

(1)实现:

 

几种线程池,都是通过  ThreadPoolExecutor 来实现的,如下:

 

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

 

 

newFixedThreadPool :

 

  public static ExecutorService newFixedThreadPool(int paramInt)
  {
    return new ThreadPoolExecutor(paramInt, paramInt, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
  }

 

而 LinkedBlockingQueue的实现:

 

  public LinkedBlockingQueue()
  {
    this(2147483647);
  }

 

这个默认的构造函数,实际上是有一些问题的(实际是构造了一个大小为 Integer.MAX_VALUE的任务队列)。

 

(2)问题

我们设想一个场景,客户端/服务器工作模式,请求来得很快,服务器端accept之后,将Socket放到了任务队列中,读请求处理,并发送响应。客户端连接来得很快,但处理没有那么快(例如需要IO或大量数学运算),所以来了之后就都排在队列里。一直到2147483647。

 

但是实际上,如果一个新的任务排在第100甚至1000、10000,客户端都可以等待,但是如果排到了 1000,000,客户端还会等待着吗?就像你如果去银行办业务,眼看排队都排到街上了,今天肯定轮不到了,你还会继续等吗?

 

换成计算机的设计语言,客户端连接,按照约定俗成,都是有超时的,开始提交了请求自然会等待,一定时间内得不到响应就超时进入异常处理流程了,那么,服务器队列里那个Socket还有什么意义呢?

 

(3)结论

 

所以说,在设计时,队列的长度是一定要用心设计和考虑的,除了在Demo和简单测试一下的程序里,不要轻易而简单的使用newFixedThreadPool ,要想清楚它的问题,在使用时使用其它方式避免。

 

一般情况下,队列的大小遵循下面的公事:

 

 queSize <= ClientTimeOut(秒) * TPS

 

队列大小 小于等于 客户端超时 * 每秒处理的交易数

 

当然,这些数据都是估算,另外,也取决于你做的东西,对于客户端超时早就走了,服务器端还得处理这种情况是一种什么态度和需求。

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值