线程池的线程数是怎么确定的?

《Java8 实战》P233

mageMogr2/auto-orient/strip%7CimageView2/2/w/500
mageMogr2/auto-orient/strip%7CimageView2/2/w/500

解释一下:

线程池大小的设置要考虑的因素很多,单纯只考虑任务特性是cpu密集型还是io密集型的情况下:cpu密集型,计算比较多通常设置N*cpu核数,IO密集型,数据库操作比较较多,设置2*cpu核数。对于混合型的,《Java8 实战》P233 有这样一个公式,图2公式变形之后可知,在cpu核数只有1个且要求cpu使用率100%,Nth = 1,也就是说设置线程数为1;同理,cpu核数为1,w:c = 1 :1,cpu使用率要达到100%,Nth = 2,即cpu核数设置为2。在这种情况下可以用红色箭头方向解释,单位时间内,前半段第一个线程进行cpu使用,后半段io的时候,第二个线程使用cpu达到cpu使用率100%。但注意,在实际中线程池线程数设置要考虑的因素很多往往并没有按照如上公式严格执行。

如何合理配置线程池(多种情况考虑):

1.分析任务特性

根据任务特性任务的性质:CPU密集型任务,IO密集型任务和混合型任务。

任务的优先级:高,中和低。

任务的执行时间:长,中和短。

任务的依赖性:是否依赖其他系统资源,如数据库连接。

2.任务性质不同的任务可以用不同规模的线程池分开处理。CPU密集型任务配置尽可能小的线程,如配置Ncpu+1个线程的线程池。IO密集型任务则由于线程并不是一直在执行任务,则配置尽可能多的线程,如2*Ncpu。混合型的任务,如果可以拆分,则将其拆分成一个CPU密集型任务和一个IO密集型任务,只要这两个任务执行的时间相差不是太大,那么分解后执行的吞吐率要高于串行执行的吞吐率,如果这两个任务执行时间相差太大,则没必要进行分解。我们可以通过Runtime.getRuntime().availableProcessors()方法获得当前设备的CPU个数。

3.优先级不同的任务可以使用优先级队列PriorityBlockingQueue来处理。它可以让优先级高的任务先得到执行,需要注意的是如果一直有优先级高的任务提交到队列里,那么优先级低的任务可能永远不能执行。

4.执行时间不同的任务可以交给不同规模的线程池来处理,或者也可以使用优先级队列,让执行时间短的任务先执行。

5.依赖数据库连接池的任务,因为线程提交SQL后需要等待数据库返回结果,如果等待的时间越长CPU空闲时间就越长,那么线程数应该设置越大,这样才能更好的利用CPU。

6.建议使用有界队列,有界队列能增加系统的稳定性和预警能力,可以根据需要设大一点,比如几千。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Java线程池 [toc] 什么是线程池 线程池就是有N个子线程共同在运行的线程组合。 举个容易理解的例子:有个线...
    石家志远阅读 5,126评论 0 6
  • layout: posttitle: 《Java并发编程的艺术》笔记categories: Javaexcerpt...
    xiaogmail阅读 11,121评论 1 19
  • 阳光普照的日子,一家人又团聚在一起。孩子们长势喜人,大人们依旧辛勤。
    神奇魔刀小姐姐阅读 1,300评论 0 0
  • 人的一生,总是拥有太多的愿望,但时间却很少,我们想要做好每一件想要做的事情,可是到头来却发现,每一件事情都没有做好...
    Molly_zhang阅读 734评论 0 0
  • 今天,我们下午16点在家出发, 坐着小车去柳州。 在去柳州的路上, 我们看见青山绿水,山上长着茂密的树...
    19e5e6df44f0阅读 2,372评论 0 1