java线程池的使用在很多客户端开发过程中都是必不可少的,主要是为了减少在线程创建和销毁时产生的系统资源消耗,提高客户端的性能.之前对线程池并没有深入的了解,最近在项目中遇到了一个问题,使用threadpoolexecutor.submit(runable)之后,runable的run方法并没有回调,所以去看一遍源码,为了加深巩固自己的理解,整理成博客,另外,我将Android系统的ThreadPoolExecuter类的源码copy下来作为我们demo中的一个类,方便我们调试,项目demo附带源码地址如下:demo和源码地址。
使用方法很简短,首先初始化线程池:
//各个参数的含义下面会结合源码介绍
ThreadPoolExecutor sExecutorService = new ThreadPoolExecutor(
5,
MAX_POOL_SIZE,
KEEP_ALIVE,
TimeUnit.SECONDS,limitedQueue,
new DefaultThreadPoolFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());
传入需要在线程执行的任务:
sExecutorService.submit(new Runnable() {
@Override
public void run() {
try {
Log.d(TAG, "run: value:"+value);
value++;
} catch (Exception e) {
e.printStackTrace();
}
}
});
以上就是线程池的大致用法,下面我们结合源码来分析一下线程池的工作原理:
1. 线程池状态和数量,一个int四个字节,32位,前三位便是线程池状态,后三位表示线程池里面线程的数量:
//记录线程池状态和线程数量(总共32位,前三位表示线程池状态,后29位表示线程数量)
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//线程数量统计位数29 Integer.SIZE=32
private static final int COUNT_BITS = Integer.SIZE - 3;
//容量 000 11111111111111111111111111111
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
//运行中 111 00000000000000000000000000000
private static final int RUNNING = -1 << COUNT_BITS;
//关闭 000 00000000000000000000000000000
private static final int SHUTDOWN = 0 << COUNT_BITS;
//停止 001 00000000000000000000000000000
private static final int STOP = 1 << COUNT_BITS;
//整理 010 00000000000000000000000000000
private static final int TIDYING = 2 << COUNT_BITS;
//终止 011 00000000000000000000000000000
private static final int TERMINATED = 3 << COUNT_BITS;
//获取运行状态(获取前3位)
private static int runStateOf(int c) { return c & ~CAPACITY; }
//获取线程个数(获取后29位)
private static int workerCountOf(int c) { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
- RUNNING:接受新任务并且处理阻塞队列里的任务
- SHUTDOWN:拒绝新任务但是处理阻塞队列里的任务
- STOP:拒绝新任务并且抛弃阻塞队列里的任务同时会中断正在处理的任务
- TIDYING:所有任务都执行完(包含阻塞队列里面任务)当前线程池活动线程为0,将要调用terminated方法
- TERMINATED:终止状态。terminated方法调用完成以后的状态
2. 线程池的状态转换:
RUNNING -> SHUTDOWN
显式调用shutdown()方法, 或者隐式调用了finalize()方法
(RUNNING or SHUTDOWN) -> STOP
显式调用shutdownNow()方法
SHUTDOWN -> TIDYING
当线程池和任务队列都为空的时候
STOP -> TIDYING
当线程池为空的时候
TIDYING -> TERMINATED
当 terminated() hook 方法执行完成时候
注:只有在RUNNING和SHUTDOWN状态下线程池才可以接受任务。
3. 线程池的构造方法和含义(有四个构造方法,最终都是调用下面的方法)
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,