在某些场景下单线程的处理能力会很低,而且还不能充分利用系统资源,所以我们会使用多线程来进行处理。所以呢在实际的项目开发中会定义不同的支持多线程的线程池对象来提升业务并发处理能力。
我们是这样定义线程池对象的(订单系统的真实代码):ThreadPoolExecutor CALLER_RUNS = new ThreadPoolExecutor(50, 1000, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(300), new BasicThreadFactory("caller-runs-pool"), new CallerRunsPolicy())。观察这一行代码,你会发现ThreadPoolExecutor有好几个参数值是定义死的,比如corePoolSize、maximumPoolSize、keepAliveTime、workQueue。
如果我们的业务量没有大增大减都是比较平稳的话,我们在定义这几个参数值的时候想必都是经过实际压测定义好的固定值,这也没有问题。但是如果业务量在今后超过了压测时的峰值,而且这种趋势还保持长时间稳定,导致线程池资源利用率很高或者不够用就得触发拒绝策略,这时候我们就要修改这些参数值了,那我们需要重新开发重新发布上线。又或者业务量长时间降到了很低的水平,导致线程池资源利用率不高,很多的线程处于闲置状态(当然了我们可以配置核心线程和非核心线程都通过keepAliveTime来进行空闲退出)。如何感知观察到业务对线程池的使用情况并给予及时的人工干预而不是改代码发版上线就成了问题。