这个问题手写应该知道,目前cpu 的核数,因为只有知道了核数,才可以预估出最佳的线程池大小
什么意思呢?
io密集型 就是类似于有io操作那种,耗时较长,那么CPU处理一个线程的时候就很空闲
密集型任务,就是耗时较短的操作,那么处理一个线程CPU,可能会非常忙
1 对于不同性质的任务来说,CPU密集型任务应配置尽可能小的线程,如配置CPU个数+1的线程数,IO密集型任务应配置尽可能多的线程,因为IO操作不占用CPU,不要让CPU闲下来,应加大线程数量,如配置两倍CPU个数+1
2 若任务对其他系统资源有依赖,如某个任务依赖数据库的连接返回的结果,这时候等待的时间越长,则CPU空闲的时间越长,那么线程数量应设置得越大,才能更好的利用CPU。当然具体合理线程池值大小,需要结合系统实际情况
那么当为密集型任务的时候,如果线程池数目设置的很大,那么就会导致CPU频繁切换上下文,浪费CPU,这个时候的线程池数据应尽量接近CPU数目
当为IO密集型任务,如果线程池数目设置过小,会导致很多时候,CPU都在等待IO操作,浪费CPU资源,所以此时应该合理扩大线程池数目;
如果是CPU密集型应用,则线程池大小设置为N+1
如果是IO密集型应用,则线程池大小设置为2N+1
也就是说,要根据业务的具体时间情况,确定线程池的大小;自己区分业务类型,当然也会有混合型任务,既有io操作,又有密集型存在,这种情况,可以选择将任务拆分,然后用两个线程池搞定,但是正常来说,这种可以按照密集型任务处理;
最近得知一个线程池计算的一个公式:
N = Ncpu * Ucpu * (1+ W/C)
Ncpu 当前计算机的cpu数量
Ucpu 期望cpu的利用率
W 线程等待时间(任务类型: 是密集型还是io型)
C 线程计算时间(任务类型: 是密集型还是io型)
个人理解: 例如 我有一个单核cpu 想要达到计算为为百分之百,现在正在执行一个任务, 等待时间与计算时间相等, 那么 就是 1 * 100% * (1+ 50&/50%) = 2
不用公式,我们想一下,也是设置两个嘛,如果设置一个,它就有50%的时间,在等待,闲置,利用率就不会达到百分之百
mytaskexecutor.corePoolSize=5
mytaskexecutor.maxPoolSize=10
mytaskexecutor.keepAliveSeconds=60
mytaskexecutor.queueCapacity=25
@Configuration
public class ThreadPoolConfig {
@Value("${mytaskexecutor.corePoolSize}")
private int corePoolSize;
@Value("${mytaskexecutor.maxPoolSize}")
private int maxPoolSize;
@Value("${mytaskexecutor.keepAliveSeconds}")
private int keepAliveSeconds;
@Value("${mytaskexecutor.queueCapacity}")
private int queueCapacity;
@Bean(name = "myTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setKeepAliveSeconds(keepAliveSeconds);
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix("MyTaskExecutor-");
executor.initialize();
return executor;
}
}
- 核心线程数(corePoolSize):这是线程池启动后最初创建的线程数。线程池会保持这个数量的线程在线程池中,即使没有任务需要执行。如果线程池中的线程空闲时间达到了一个时间阈值(keepAliveTime),线程会被回收。
- 最大线程数(maximumPoolSize):线程池可以创建的最大线程数。如果核心线程数已满,并且提交的任务超过了已完成任务数与核心线程数的差值,那么线程池会创建更多的线程,直到达到这个上限。
- 非核心线程存活时间(keepAliveSeconds):线程池可以创建的最大线程数。如果核心线程数已满,并且提交的任务超过了已完成任务数与核心线程数的差值,那么线程池会创建更多的线程,直到达到这个上限。
- 线程池中的任务队列长度(queueCapacity):queueCapacity指当线程池中的线程数量达到corePoolSize后,新提交的任务会被放在任务队列中等待执行,这个等待执行的队列长度就是queueCapacity。如果队列满了(即已有任务队列长度等于queueCapacity),再提交新的任务时,线程池会创建新的线程(如果当前线程数小于maxPoolSize)或者拒绝新任务(如果当前线程数已经达到maxPoolSize)。