线程池
线程池七大参数:
-
corePoolSize:线程池里常驻的核心线程数,也是线程池中拥有的最小线程数量,即使处于空闲状态也不会被销毁。
- 创建线程后,有请求任务到来时就会安排池中的线程去执行请求任务
- 当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列中。
-
maximumPoolSize:线程池能够容纳同时执行的最大线程数,maximumPoolSize>=corePoolSize,如果任务非常多corePoolSize目前无法出来,并且缓存队列也已经排满,那么可用线程的数量就会增加但是不会超过maximumPoolSize。
-
keepAliveTime:多余的空闲线程的存活时间。当前线程池的数量超过corePoolSize时,且超过部分的空闲时间达到此参数时,那么多余的线程就会被销毁,剩余corePoolSize个。
-
unit:keepAliveTime的单位。
-
workQueue:任务队列,已经提交但是尚未执行的任务。
-
threadFactory:表示生产线程池中工作线程的线程工厂一般使用默认值。
-
handler:当工作队列中的任务已满并且线程池中的线程数量也达到最大,这时如果有新任务提交进来,拒绝策略就是解决这个问题的,jdk中提供了4中拒绝策略:
①CallerRunsPolicy
该策略下,回退由调用线程池的线程处理该任务
②AbortPolicy
该策略下,直接丢弃任务,并抛出RejectedExecutionException异常。
③DiscardPolicy
该策略下,直接丢弃任务,什么都不做。
④DiscardOldestPolicy
该策略下,抛弃最早进入队列的那个任务,然后尝试把这次拒绝的任务放入队列。
执行流程
- 线程池中线程数小于corePoolSize时,新任务将创建一个新线程执行任务,不论此时线程池中存在空闲线程;
- 线程池中线程数达到corePoolSize时,新任务将被放入workQueue中,等待线程池中任务调度执行;
- 当workQueue已满,且maximumPoolSize>corePoolSize时,新任务会创建新线程执行任务;
- 当workQueue已满,且提交任务数超过maximumPoolSize,任务由RejectedExecutionHandler处理;
- 当线程池中线程数超过corePoolSize,且超过这部分的空闲时间达到keepAliveTime时,回收该线程;
- 如果设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize范围内的线程空闲时间达到keepAliveTime也将回收;
参数设置
CPU密集型
CPU密集的意思是该任务需要大量的运算,而没有阻塞,CPU一直全速运行。CPU密集任务只有在真正的多核CPU上才可能得到加速(通过多线程),而在单核CPU上,无论你开几个模拟的多线程该任务都不可能得到加速,因为CPU总的运算能力就那些。CPU密集型任务配置尽可能少的线程数量:以保证每个CPU高效的运行一个线程。
一般公式:(CPU核数+1)个 线程的线程池IO密集型
I0密集型,即该任务需要大量的IO,即大量的阻塞。在单线程上运行I0密集型的任务会导致浪费大量的CPU运算能力浪费在等待。
所以在IO密集型任务中使用多线程可以大大的加速程序运行,即使在单核CPU上,这种加速主要就是利用了被浪费掉的阻塞时间。I0密集型时,大部分线程都阻寒,故需要多配置线程数:
公式:CPU核数 * 2
CPU核数 / (1 - 阻塞系数) 阻塞系数 在0.8~0.9之间
查看CPU核数:
System.out.println(Runtime.getRuntime().availableProcessors());