Java 线程池理解
线程池:管理线程的池子
1.使用线程池的好处
1.管理线程降低资源损耗(体现在线程的创建和线程销毁上)
2.提高响应速度 (通过线程池获取线程肯定比从新创建一个新的线程要快)
3.重复利用 (线程使用完毕,重新放回,节省资源)
2.线程池的创建
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
核心参数
a.corePoolSize : 线程池核心线程数最大值
b.maximumPoolSize: 线程池最大线程数大小
c.keepAliveTime:线程池中非核心线程空闲存活时间大小
d.unit:空闲线程存活时间单位
e.workQueue:存放任务的阻塞队列
f.threadFactory:用于设置创建线程的工厂
g.handler:线程池的饱和策略事件
3.线程池的执行流程
-首先提交一个任务,线程池中存活的核心线程数小于核心线程数最大值时,创建一个核心线程处理提交的任务。
-如果核心线程数已满,提交的任务就会被放到任务队列workQueue 等待执行
-当线程池存活的线程数已经等于核心线程数最大值时,并且任务队列也满了,判断线程数是否达到线程池线最大线程数,最大线程数是否已满,没达到创建一个非核心线程执行提交的任务。
-已经达到最大线程数,还有新的任务过来,直接采用拒绝策略处理。
4.线程池的四种拒绝策略
a.AbortPolicy: 抛出默认异常
b.DiscardPolicy: 直接丢弃任务
c.DiscardOldestPolicy: 丢弃队列最老的任务,将当前任务提交给线程池。
d.CallerRunsPolicy: 交给线程池调用所在的线程进行处理
5.线程池的异常处理
使用线程池处理任务时,可能会抛出运行时代码异常,抛出异常后 线程池可能会捕获它,也可能会创建一个新的线程来代替异常的线程,我们也无法感知出现了异常,因此我们需要考虑线程池异常的情况。
a.提交一个新的任务,如何处理异常
经典面试题
1.Java的线程池说一下,各个参数的作用,如何进行的?
线程池帮助我们管理线程,有 降低资源损耗,响应快,可重复利用等优点。
主要有以下几个核心参数
a.线程池核心线程数最大值
b.线程池最大线程数大小
c.线程池非核心线程空闲存活的时间大小
d.空闲线程存活时间单位
e.任务队列
f.设置创建线程的工厂
g.线程池饱和的策略事件
运行:提交一个任务,存活核心线程数是否小于线程池核心线程数大小 小于的话 创建核心线程处理任务---超过的话将任务提交到任务队列
如果存活的线程数等于线程池核心线程数最大值,并且任务队列已满,判断线程数是否达到最大线程数,没达到创建一个非核心线程执行提交的任务
达到线程池最大数,并且还有新的任务过来,采用拒绝策略处理。
2.按线程池内部机制,当提交新任务时,有哪些异常要考虑。
a. try catch 处理任务块代码的异常
b.Future 对象的get 方法 可以接收submit 执行流程的异常
c.为工作者线程设置UncaughtExceptionHandler,在uncaughtException方法中处理异常
d.重写ThreadPoolExecutor的afterExecute 方法 处理传递的异常引用
3.线程池有哪几种工作队列?
a.ArrayBlocKingQueue :用一个有序数组实现的有界阻塞队列 按FIFO排序量
b.LinkedBlockingQueue :可设置容量的队列,不设置将是一个无边界的阻塞队列 最大长度为Integer.max.value
c.DelayQueue : 延迟队列
d.PriorityBlockingQueue :优先级队列 优先级无边界阻塞队列
e.SynchronousQueue :同步队列
4.几种常用的线程池
a.newFixedThreadPool 固定数目线程的线程池
b.newCachedThreadPool 可缓存线程的线程池
c.newSingleThreadExecutor 单线程的线程池
d.newScheduledThreadPool 定时及周期的线程池