这个问题手写应该知道,目前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;
    }
}
  1. 核心线程数(corePoolSize):这是线程池启动后最初创建的线程数。线程池会保持这个数量的线程在线程池中,即使没有任务需要执行。如果线程池中的线程空闲时间达到了一个时间阈值(keepAliveTime),线程会被回收。
  2. 最大线程数(maximumPoolSize):线程池可以创建的最大线程数。如果核心线程数已满,并且提交的任务超过了已完成任务数与核心线程数的差值,那么线程池会创建更多的线程,直到达到这个上限。
  3. 非核心线程存活时间(keepAliveSeconds):线程池可以创建的最大线程数。如果核心线程数已满,并且提交的任务超过了已完成任务数与核心线程数的差值,那么线程池会创建更多的线程,直到达到这个上限。
  4. 线程池中的任务队列长度(queueCapacity):queueCapacity指当线程池中的线程数量达到corePoolSize后,新提交的任务会被放在任务队列中等待执行,这个等待执行的队列长度就是queueCapacity。如果队列满了(即已有任务队列长度等于queueCapacity),再提交新的任务时,线程池会创建新的线程(如果当前线程数小于maxPoolSize)或者拒绝新任务(如果当前线程数已经达到maxPoolSize)。