声明:本篇文章已授权微信公众号 YYGeeker 独家发布
前言
多线程并发是我们在开发中经常遇到的问题,提及线程池,首先我们得了解线程的相关知识。关于线程的详情介绍本文就不提及了,有不太清楚的朋友可以自行查找相关资料,下面简要概述一下进程和线程的概念,为后续内容(线程池)做铺垫。
进程:
每个app运行时前首先创建一个进程,该进程是由Zygote fork出来的,用于承载App上运行的各种Activity/Service等组件。
进程对于上层应用来说是完全透明的,这也是google有意为之,让App程序都是运行在Android Runtime。大多数情况一个App就运行在一个进程中,除非在AndroidManifest.xml中配置Android:process属性,或通过native代码fork进程。
线程:
线程对应用来说非常常见,比如每次new Thread().start都会创建一个新的线程。该线程与App所在进程之间资源共享,从Linux角度来说进程与线程除了是否共享资源外,并没有本质的区别,都是一个task_struct结构体,在CPU看来进程或线程无非就是一段可执行的代码,CPU采用CFS调度算法,保证每个task都尽可能公平的享有CPU时间片。
上述引自 :知乎 Gityuan的回答
本文就以下几个问题展开讲解:
- 线程池的基本概念。
- 采用线程池的优势。
- Android 中常用的几种线程池。
- 如何终止某个线程任务。
一、关于线程池
Android中的线程池的概念来源于Java中的Executor,它们的使用基本是一致的。Executor是一个接口,真正的线程池的实现为ThreadPoolExecutor。ThreadPoolExecutor提供了一系列参数来配置线程池,Android中常用的几种线程池都是通过对ThreadPoolExecutor进行不同配置来实现的。
ThreadPoolExecutor 构造方法
ThreadPoolExecutor 有多个重载方法,但最终都调用了这个构造方法:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory)
我们可以看到,这个构造方法里一共有7个参数,其参数的含义如下:
corePoolSize: 线程池中核心线程的数量。
maximumPoolSize: 线程池中最大线程数量。
keepAliveTime: 非核心线程的超时时长,当系统中非核心线程闲置时间超过keepAliveTime之后,则会被回收。如果ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true,则该参数也表示核心线程的超时时长。
unit: keepAliveTime这个参数的单位,有纳秒、微秒、毫秒、秒、分、时、天等。
workQueue: 线程池中的任务队列,该队列主要用来存储已经被提交但是尚未执行的任务。存储在这里的任务是由ThreadPoolExecutor的execute方法提交来的。
threadFactory: 为线程池提供创建新线程的功能,这个我们一般使用默认即可。
handler: 拒绝策略,当线程无法执行新任务时(一般是由于线程池中的线程数量已经达到最大数或者线程池关闭导致的),默认情况下,当线程池无法处理新线程时,会抛出一个RejectedExecutionException。
两个执行的方法
ThreadPoolExecutor有两个方法可以供我们执行,分别是submit()和execute(),我们先来看看这两个方法到底有什么差异
execute()方法源码:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
//获得当前线程的生命周期对应的二进制状态码
int c = ctl.get();
//判断当前线程数量是否小于核心线程数量,如果小于就直接创建核心线程执行任务,创建成功直接跳出,失败则接着往下走.
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//判断线程池是否为RUNNING状态,并且将任务添加至队列中.
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
//审核下线程池的状态,如果不是RUNNING状态,直接移除队列中
if (! isRunning(recheck)