JAVA多线程之线程池
为什么要使用线程池
- 降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗;
- 提高系统响应速度,当有任务到达时,通过复用已存在的线程,无需等待新线程的创建便能立即执行;
- 方便线程并发数的管控。因为线程若是无限制的创建,可能会导致内存占用过多而产生OOM,并且会造成cpu过度切换(cpu切换线程是有时间成本的(需要保持当前执行线程的现场,并恢复要执行线程的现场))。
ThreadPoolExecutor
corePoolSize :线程池的核心池大小,在创建线程池之后,线程池默认没有任何线程。当有任务过来的时候才会去创建创建线程执行任务。换个说法,线程池创建之后,线程池中的线程数为0,当任务过来就会创建一个线程去执行,直到线程数达到corePoolSize 。如果还有任务加入则会将任务加入到BlockingQueue中。注意:当向线程池提交一个任务时,若线程池已创建的线程数小于corePoolSize,即便此时存在空闲线程,也会通过创建一个新线程来执行该任务。
- prestartCoreThread(); 可以提前创建一个线程。
- prestartAllCoreThreads():可以提前创建所有的核心线程。
maximumPoolSize:线程池所允许的最大线程个数。当队列满了,且已创建的线程数小于maximumPoolSize,则线程池会创建新的线程来执行任务。另外,对于无界队列,可忽略该参数。按照上面代码中的参数来说明:当添加的任务数大于 corePoolSize+blockQueue.size时,该参数将会生效;即当我向线程池提交22个任务,此时executor.getPoolSize()=6。
keepAliveTime:线程存活保持时间;当线程池中线程数大于核心线程数时,线程的空闲时间如果超过线程存活时间,那么这个线程就会被销毁,直到线程池中的线程数小于等于核心线程数。
TimeUnit:keepAliveTime的单位;
workQueue:任务队列,用于存储等待执行任务的阻塞队列。
threadFactory:线程工厂,用于创建新线程。threadFactory创建的线程也是采用new Thread()方式,threadFactory创建的线程名都具有统一的风格:pool-m-thread-n(m为线程池的编号,n为线程池内的线程编号)。
handler:线程饱和策略,当线程池和队列都满了,再加入线程会执行此策略。