为什么用线程池
1.创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处理效率
2.线程并发数量过多,抢占系统资源从而导致阻塞
3.对线程进行一些简单的管理
线程池ThreadPoolExecutor
既然Android中线程池来自于Java,那么研究Android线程池其实也可以说是研究Java中的线程池
在Java中,线程池的概念是Executor这个接口,具体实现为ThreadPoolExecutor类,学习Java中的线程池,就可以直接学习他了。
对线程池的配置,就是对ThreadPoolExecutor构造函数的参数的配置,既然这些参数这么重要,就来看看构造函数的各个参数吧
ThreadPoolExecutor提供了四个构造函数
我知道你看到这些构造函数和我一样也是吓呆了,但其实一共就7种类型,理解起来简直和理解一周有7天一样简单,而且一周有两天是周末,其实也就只有5天需要了解!相信我,毕竟扯皮,我比较擅长。以下是五个需要了解的
一、int corePoolSize => 该线程池中核心线程数最大值
![](https://i-blog.csdnimg.cn/blog_migrate/aaf348681698077704fc4f5cafa0b071.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2aa2a5a63cab78ffcf56a0bd75ccccf9.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0c0b09655ef4e376c5c2a58b2cab53b3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/5b80ca38c3fab6bf3c861aadfda94a1f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/443a848198028916851a35bdba5a7dc4.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8fe3483da7d07f37a738b495613dc402.png)
![](https://i-blog.csdnimg.cn/blog_migrate/5259e3164c3988dc9cb55f48bd4b14df.png)
新建一个线程池的时候,一般只用前5个参数的构造函数。
向ThreadPoolExecutor添加任务
那说了这么多,你可能有疑惑,我知道new一个ThreadPoolExecutor,大概知道各个参数是干嘛的,可是我new完了,怎么向线程池提交一个要执行的任务啊?
通过ThreadPoolExecutor.execute(Runnable command)
方法即可向线程池内添加一个任务
ThreadPoolExecutor的策略
上面介绍参数的时候其实已经说到了ThreadPoolExecutor执行的策略,这里给总结一下,当一个任务被添加进线程池时:
- 线程数量未达到corePoolSize,则新建一个线程(核心线程)执行任务
- 线程数量达到了corePools,则将任务移入队列等待
- 队列已满,新建线程(非核心线程)执行任务
- 队列已满,总线程数又达到了maximumPoolSize,就会由上面那位星期天(RejectedExecutionHandler)抛出异常
常见四种线程池
如果你不想自己写一个线程池,那么你可以从下面看看有没有符合你要求的(一般都够用了),如果有,那么很好你直接用就行了,如果没有,那你就老老实实自己去写一个吧
Java通过Executors提供了四种线程池,这四种线程池都是直接或间接配置ThreadPoolExecutor的参数实现的,下面我都会贴出这四种线程池构造函数的源码,各位大佬们一看便知!
来,走起:
CachedThreadPool()
可缓存线程池:
- 线程数无限制
- 有空闲线程则复用空闲线程,若无空闲线程则新建线程
- 一定程序减少频繁创建/销毁线程,减少系统开销
创建方法:
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
源码:
通过我上面行云流水谈笑风生天马行空滔滔不绝的对各种参数的说明,这个源码你肯定一眼就看懂了,想都不用想(下面三种一样啦)
FixedThreadPool()
定长线程池:
- 可控制线程最大并发数(同时执行的线程数)
- 超出的线程会在队列中等待
创建方法:
源码:
2个参数的构造方法源码,不用我贴你也知道他把星期六放在了哪个位置!所以我就不贴了,省下篇幅给我扯皮
ScheduledThreadPool()(用的较少,一般另外三个就可以满足需要)
定长线程池:
- 支持定时及周期性任务执行。
创建方法:
源码:
SingleThreadExecutor()
单线程化的线程池:
- 有且仅有一个工作线程执行任务
- 所有任务按照指定顺序执行,即遵循队列的入队出队规则
创建方法:
ExecutorService singleThreadPool = Executors.newSingleThreadPool();
源码:
还有一个Executors.newSingleThreadScheduledExecutor()
结合了3和4,就不介绍了,基本不用。