Android 中的线程池就是 java 中的线程池,即 ThreadPoolExecutor 类。
Java 通过 Executors 提供四种线程池:
- newCachedThreadPool
创建一个可缓存的线程池
- newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
- newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。
- newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
Executors 是一个线程池的工具类,上面四个方法最终都是调用的 ThreadPoolExecutor
。理解 ThreadPoolExecutor 就可以完全理解线程池。
线程池解决了 2 个问题:
- 当执行大量异步任务时,通过减少每个任务的调用开销来提高性能。
- 提供了限制管理线程资源的方法。
ThreadPoolExecutor
public class ThreadPoolExecutor extends AbstractExecutorService
构造
/**
*
* @param corePoolSize 保持在线程池中的线程数,即使线程处于空闲状态,除非设置了 allowCoreThreadTimeOut
* @param maximumPoolSize 线程最大数量
* @param keepAliveTime 线程数大于 corePoolSize 时,线程池中的空闲线程等待新任务执行的最大时间,超过这个时间,空闲线程就会被终止。
* @param unit keepAliveTime 的时间单位
* @param workQueue 任务队列
* @param threadFactory 线程工厂
* @param handler 线程被阻塞时的处理者,因为到达了线程的最大数量或者任务队列满了。
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
// 检查参数
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
// 赋值
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
执行流程
执行流程可以用这张图来概括:
通过 execute()
方法执行线程池,内部会自动根据我们构造参数的信息分配处理 Runnable。
public void execute(Runnable command) {
// Runnable 不可以为空
if (command == null)
throw new NullPointerException();
// ctl 是一个 AtomicInteger,用来记录正在运行的线程数量
int c = ctl.get();
// 当前核心的线程数量<corePoolSize,就新开一个线程将任务放进去
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
// 核心线程正在运行,且任务队列没满
if (isRunning(c) && workQueue.offer(command)) {
// 重新检查核心线程
int recheck = ctl.get();
// 核心线程没有运行就移除任务,实施拒绝策略
if (! isRunning(recheck) && remove(command))
reject(command);
// 核心线程数量为0,开一个线程
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
// 任务队列
else if (!addWorker(command, false))
reject(command);
}