线程池用处:
1.能够重复利用已被创建的线程,减小系统创建线程的过程,而让系统的精力能过多的放在执行任务上
2.合理的配置线程池,能够高效的利用系统资源,能够防止过多的线程导致系统资源不足。
风险:
用线程池构建的应用程序容易遭受任何其它多线程应用程序容易遭受的所有并发风险,诸如同步错误和死锁,它还容易遭受特定于线程池的少数其它风险,诸如与池有关的死锁、资源不足和线程泄漏
使用场景:
1.ListView滑动,获取大量图片的时候
2.频繁的网络请求,获取接口数据的时候
详解:
ThreadPoolExecutor 实现了ExecutorService接口,通过此类,可以创建一个自己的线程池类
// ThreadPoolExecutor 的构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
........................
}
参数说明:
corePoolSize 池中所保存的线程数,包括空闲线程
maximumPoolSize 池中允许的最大线程数
keepAliveTime 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间
unit keepAliveTime参数的时间单位
workQueue 执行前用于保持任务的队列,此队列仅保持由execute方法提交的Runnable任务
hander 由于超出线程范围和队列容量而使执行被阻塞时所使用的处理程序
核心池与最大池大小详解
当执行execute方法提交新任务时
1.如果运行的线程少于corePoolSize,则创建新的线程来处理请求,即使池中有其他空闲的线程。
2.如果运行的线程多于corePoolSize而少于maximumPoolSize,则仅当队列满时才创建新的线程
3.如果corePoolSize的大小与maximumPoolSize相同,则创建了固定大小的线程池。因为如果线程数量大于corePoolSize且队列也满的时候,线程池会继续创建maximumPoolSize-corePoolSize个线程数,而此时两个相等,说明corePoolSize满了之后,线程池不会再创建新的线程,故而此时固定大小的线程池
4.如果maximumPoolSize设置为Integer.MAX_VALUE,则是一个无界的线程池,允许池适应任意数量的并发任务。
其他详解:
1.默认情况下,线程池只有新任务到达的时候才会创建和启动线程,但是有时候我们想线程池实例化之后,立马创建核心数量的执行线程,那么可以使用 prestartCoreThread()和prestartAllCoreThreads()方法。
2.可以在线程池执行过程中动态调整corePoolSize与maximumPoolSize的值,setCorePoolSize(int)和setMaximumPoolSize(int)
3.如果池中当前有多于corePoolSize的线程,则这些多出的线程在空闲时间超过keepAliveTime时将会终止
4.所有的BlockingQueue都可用于传输和保持提交的任务,可以使用此队列与池大小进行交互
4.1 如果运行的线程少于corePoolSize,则Executor始终首选添加新的线程,而不进行排队
4.2 如果运行的线程等于或多于corePoolSize,则Executor始终首选请求加入队列,而不添加新的线程
4.3 如果无法加入队列,则创建新的线程,除非创建此线程超出maximumPoolSize,则任务将被拒绝