1.线程池的优势
(1).降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗;
(2).提高系统响应速度,当有任务到达时,通过重用已存在的线程,无需等待新线程的创建便能立即执行;
(3).方便线程并发数的管控。因为线程若是无限制的创建,可能会导致内存占用过多而产生OOM,并且造成CPU过度切换
(4).提供更强大的功能,延时定时线程池。
2.线程池的主要参数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
1.corePoolSize(线程池基本大小):当向线程池提交一个任务时,若线程池已创建的线程数小于corePoolSize,即便此时存在空闲线程,也会通过创建一个新线程来执行该任务,指导已创建的线程数大于或者等于corePoolSize时
2.maxinumPoolSize(线程池最大大小):线程池所允许的最大线程个数。当队列满了,且已创建的线程数小于maxinumPoolSize,则线程池会创建新的线程来执行任务。另外,对于无界队列,可以忽略该参数。
3.keepAliveTime(线程存活保持时间)当线程池中的线程数大于核心线程数时,线程的空闲时间如果超过线程存活的时间,那么这个线程就会被销毁,知道线程池中的线程个数小于核心线程数
4.workQueue(任务队列):用于传输和保存等待执行任务的阻塞队列
5.threadFactory(线程工厂):用于创建新线程,threadFactory创建的线程采用Thread newThread(Runnable r);方式,
6.handler(线程饱和策略):当线程池和队列都满了,在加入线程会执行才策略。有四种:
AbortPolicy:丢弃任务,抛出RejectExecutionException异常
CallerRunsPolicy: 这个策略重试添加当前的任务,他会自动重复调用 execute() 方法,直到成功。
DiscardPolicy: 直接丢弃任务,无异常
DiscardOldestPolicy: 丢弃队列头部任务
3.线程池流程
-
如果此时线程池中的数量小于 corePoolSize ,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
-
如果此时线程池中的数量等于 corePoolSize ,但是缓冲队列 workQueue 未满,那么任务被放入缓冲队列。
-
如果此时线程池中的数量大于 corePoolSize ,缓冲队列 workQueue 满,并且线程池中的数量小于maximumPoolSize ,建新的线程来处理被添加的任务。
-
如果此时线程池中的数量大于 corePoolSize ,缓冲队列 workQueue 满,并且线程池中的数量等于maximumPoolSize ,那么通过 handler 所指定的策略来处理此任务。
核心线程 corePoolSize 、任务队列 workQueue 、最大线程 maximumPoolSize ,如果三者都满了,使用 handler处理被拒绝的任务。当线程池中的线程数量大于 corePoolSize 时,如果某线程空闲时间超过 keepAliveTime ,线程将被终止。这样,线程池可以动态的调整池中的线程数。
4.线程池为什么需要使用(阻塞)队列?
1.因为线程若是无限制的创建,可能会导致内存占用过多而产生OOM,并且会造成CPU过度切换
2.线程池创建线程添加任务需要获取mainlock这个全局锁,影响并发效率,阻塞队列可以很好的缓冲。
5.线程池为什么要使用阻塞队列而不使用非阻塞队列?
阻塞队列可以保证任务队列中没有任务时阻塞获取任务的线程,使得线程进入wait状态,释放cpu资源。
当队列中有任务时才唤醒对应线程从队列中取出消息执行,使得线程不至于一直占用CPU资源
6.java中提供的线程池
Executors类提供了4种不同的线程池:newCahcedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor

1.newCahcedThreadPool:用来创建一个可以无限扩大的线程池,适用于负载较轻的场景,执行短期异步任务.(可以使得任务快速得到执行,因为任务时间执行短,可以很快结束,也不会造成cpu过度切换)
2.newFixedThreadPool:创建一个固定大小的线程池,因为采用无界的阻塞队列,所以实际线程数量永远不会变,适用于负载较重的场景,对当前线程数量进行限制(保证线程数可控,不会造成线程过多,导致系统负载更为严重)
3.newSingleThreadExecutor:创建一个单线程的线程池,适用于需要保证顺序执行各个任务。
4.newScheduledThreadPool:适用于执行延时或者周期性任务
7.execute()和submit()方法
1.execute(),执行一个任务,没有返回值。
2.submit(),提交一个线程任务,有返回值。
网友评论