并发编程(十六):线程池概述
目录
学习资料
《Java并发编程的艺术》第9章
1.简介
线程池好处:
- 降低资源消耗:线程创建销毁会消耗资源
- 提高响应速度
- 便于管理线程
2.线程池实现原理

线程池要素:
corePool:核心线程池大小maximunPool:最大线程池大小BlockingQueue<Runnable>:任务(阻塞)队列,四种ArrayBlockingQueue:数组实现有界阻塞队列,FIFOLinkedBlockingQueue:基于链表阻塞队列,FIFO,吞吐量高于ArrayBlockingQueueSynchronousQueue:不存储元素的阻塞队列,吞吐量高于LinkedBlockingQueuePriorityBlockingQueue:一个具有优先级的阻塞队列
RejectedExecutionHandler:拒绝(饱和)策略,四种AbortPolicy:抛出异常CallerRunsPolicy:用当前线程运行任务DiscardOldestPolicy:丢弃队列里最近一个任务,并执行当前任务DiscardPolicy:不处理,丢掉
线程执行任务时会经历4个阶段:(阻塞队列不同可能具体行为不同)
- 核心:当前运行的线程少于
corePoolSize,新建线程并执行 - 阻塞:当前的线程数>=
corePoolSize,将任务加入BlockingQueue - 最大:无法加入
BlockingQueue,创建新的线程来处理任务(需要获取全局锁) - 拒绝:如果创建新线程将使当前运行的线程超出
maximumPoolSize,则拒绝,调用拒绝策略
ThreadPoolException中执行任务示意图:

线程执行任务分两种情况:
- 创建线程时提交的任务
- 反复从BlockingQueue获取任务执行
3.线程池的使用
3.1 创建线程池

七个参数:
corePoolSize:核心线程池数量,调用prstartAllCoreThreads()方法会提前启动所有线程maximumPoolSize:最大线程池数量,无界队列该参数没效果keepAliveTime:当前的线程数量大于corePoolSize,指定时间后超过的空闲线程销毁unit:keepAliveTime的单位workQueue:任务队列,4种threadFactory:线程工厂handler:拒绝策略,4种
3.2 提交任务
两个方法:
execute(runnable):提交不需要返回值的任务submit(runnable):提交需要返回值的任务- 会返回一个future类型的对象
- 可以通过
future.get()来阻塞当前线程,直到返回工作线程结果 - 可以使用超时方法
get(long timeout,TimeUnit unit)
3.3 关闭线程池
两种方式:shutdown()或shutdownNow(),原理都是 遍历+interrupt方法
shutdown():不会停止正在执行的线程,常用shutdownNow():会尝试停止所有线程,不常用
两个判断方法:
isShutDown():是否调用了上面两个方法之一isTerminated():是否所有线程停止
3.4 配置线程池
分析任务特性:
- 性质:CPU密集型,IO密集型还是混合型
- 优先级:高,中,低
- 执行时间:长,中,短
- 依赖性:是否依赖其他资源,如数据库
性质不同规模的线程池分开处理:
-
CPU密集型:线程数配置尽可能小,如
CPU个数+1 -
IO密集型:应配置尽可能多的线程,如
2*CPU数 -
混合型任务:拆分为一个CPU密集型和一个IO密集型,如果执行时间相差很大,不要拆
-
获取CPU数量:
Runtime.getRuntime().avaliableProcessors();依赖数据库连接池的任务,等待时间越长,CPU空闲时间越长,线程数应设置越大
建议使用有界队列,能增加系统稳定性和预警能力
3.5 线程池监控
系统中使用了大量线程池,可以通过线程池提供的参数进行监控,可以get以下属性:
taskCount:线程池需要执行的任务数量completedTaskCount:已完成的任务数量largestPoolSize:线程池里曾经创建过的最大线程数量getPoolSize:线程池的线程数量getActiveCount:获取活动的线程数
也可以扩展线程池方法,重写以下方法:
beforeExecute(..):执行前afterExecute(..):执行后terminated(..):关闭前
4.学习总结
1.线程池简介
- 是什么
- 好处:降低资源消耗,提高响应速度,便于管理线程
2.线程池实现原理
线程池组成:

- corePool:核心池
- maximumPool:最大池
- BlockingQueue:阻塞队列 (四种)
- ArrayBlockingQueue, LinkedBlockingQueue
- SynchronousQueue(不存储元素)
- PriorityBlockingQueue(优先级)
- 饱和拒绝策略:(四种)
抛出异常,当前线程执行,丢弃前一个,直接丢弃
线程池执行四个阶段:
核心池—>阻塞—>最大池—>拒绝
3.线程池的使用
- 创建线程池:七个参数
两个大小(核心池,最大池),两个时间(空闲时间,单位),工厂,阻塞队列,拒绝 - 提交任务:
execute():无返回值submit():返回future
- 关闭线程池
shutdown():正常终止,执行完队列中的任务shutdownNow():立即终止isShutDown():是否调用了上方法isTerminated():是否所有线程停止
- 配置线程池
- 分析任务特性:IO密集,CPU密集, 混合型
- 性质不同分配不同数量线程:
- CPU密集型:少,cpu数+1
- IO密集型:多,2倍cpu数
- 获取CPU数:
Runtime.getRuntime().avaliableProcessors(); - 建议使用有界队列
- 线程池监控
- 监控参数:
taskCount:线程池需要执行的任务数量completedTaskCount:已完成的任务数量largestPoolSize:线程池里曾经创建过的最大线程数量getPoolSize:线程池的线程数量getActiveCount:获取活动的线程数
- 扩展:
beforeExecute(..):执行前afterExecute(..):执行后terminated(..):关闭前
- 监控参数:

浙公网安备 33010602011771号