持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
为何使用线程池
之前提到过在Android中使用Thread。但Thread使用存在一些问题(频繁创建影响性能、线程资源不可控、多线程竞争无优先级等)缺少一些更细粒度主观控制能力。因此统一使用线程池可以很好帮助开发者去控制线程使用:多线程统一管理、减少资源竞争紧张问题;线程可复用性,减少频繁创建线程带来GC等性能问题。
线程池介绍
线程池的使用会使用到ExecutorService和Executors两个类。ExecutorService是接口类继承了Executors接口。Executors则实现提供了四种线程池形式,分别为newFixedThreadPool、newCachedThreadPool、newSingleThreadPool、newScheduledThreadPool。
newFixedThreadPool
该线程池是创建可复用固定线程数的线程池。根据需要创建线程数,执行固定个数线程。超出线程范围的任务会在队列中等待其他线程结束后再执行,线程数则是固定数量且可复用。
ExecutorService executorService = Executors.newFixedThreadPool(5);
for(int i = 0; i < 10;i++){
Runnable runnable = new Runnable(){
@Override
public void run(){
// xxx
}
};
executorService.execute(runnable);
}
newCachedThreadPool
该线程为可缓存线程池,线程池长度超出需求会灵活回收闲置线程。可缓存线程池大小不定,可根据需要创建不同数量线程。该类型线程池比较适用于轻量级异步任务。
ExecutorService executorService = Executors.newCachedThreadPool();
for(int i = 0; i < 10;i++){
Runnable runnable = new Runnable(){
@Override
public void run(){
// xxx
}
};
executorService.execute(runnable);
}
newSingleThreadPool
该线程池就是单一线程池,内部只有一个线程对象。可以理解等同于Executors.newFixedThreadPool(1);每次处理一个异步任务,其他任务在单联队列中等待被处理。
ExecutorService executorService = Executors.newSingleThreadPool();
for(int i = 0; i < 10;i++){
Runnable runnable = new Runnable(){
@Override
public void run(){
// xxx
}
};
executorService.execute(runnable);
}
newScheduledThreadPool
该线程池特点是支持执行定时和周期性任务,可通过调用schedule方法设置定时性任务。
ExecutorService executorService = Executors.newScheduledThreadPool(5);
for(int i = 0; i < 10;i++){
Runnable runnable = new Runnable(){
@Override
public void run(){
// xxx
}
};
executorService.schedule(runnable,1000,TimeUnit.MILLISECONDS);
}
自定义ThreadPoolExecutor
除了上述介绍的线程池之外,开发者可根据实际业务需求自定义线程池来使用。
- corePoolSize:核心线程数
- maximumPoolSize:线程池最大数
- keepAliveTime:空闲线程存活时间(超出时间会被回收)
- unit:存活时间单位
- workQueue:等待执行的任务队列
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
线程池总结
| newFixedThreadPool | newCachedThreadPool | newSingleThreadPool | newScheduledThreadPool |
|---|---|---|---|
| 核心线程和非核心线程数量相等 | 没有核心线程、只有无限非核心线程 | 核心线程只有一个 | 核心线程固定,非核心线程无限 |
| 线程空闲不会被回收 | 非核心线程结束后60s后回收 | 非核心线程会在闲置状态下回收 |
拒绝策略
在线程池中若任务数超出线程池所能容纳的数量时会触发拒绝策略。
- AbortPolicy:默认策略,丢弃任务并抛出异常
- DisCardPolicy:丢弃但不会抛出异常
- DisCardOldesPolicy:竞争第一个任务,丢弃队列最前面的任务,成功等于执行;失败就丢弃不抛出异常
- CallerRunsPolicy:在调用者所在线程去执行提交的任务。