一、线程池的作用
1、线程重用,省去线程重复创建和重复销毁的时间,提升效率
2、控制线程数,避免大量创建线程导致线程混乱堵塞
3、管理线程,控制线程的开始、状态、暂停
二、android线程池种类
android可以使用ThreadPoolExecutor类提供的方法来自定义线程
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
android也提供了工具类Executors,包含4中常用的线程池
1、CachedThreadPool
new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
CachedThreadPool核心线程数为0,所以它只有非核心线程。非核心线程数是Integer.MAX_VALUE,由于使用的是SynchronousQueue,不能排队等待,所以任务提交后会立即执行,线程闲置60s就会被回收,适合大量的非耗时任务。
2、SingleThreadExecutor
new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()))
SingleThreadExecutor只有一个核心线程,没有超时时间,可以保证任务的有序执行,由于只有一条线程,也就没有线程同步问题。
3、FixedThreadPool
new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>())
FixedThreadPool只有核心线程,如果新任务添加时所有线程都在工作则新任务排队等待,任务完成后核心线程不会收回,等待下次任务的添加。
4、ScheduledThreadPool
new ScheduledThreadPoolExecutor(corePoolSize)
ScheduledThreadPool只有核心线程,适用于需要延时或周期性执行任务的场景。
三、android中线程池经典场景
1、okhttp
异步执行任务时调用如下方法:
synchronized void enqueue(AsyncCall call) {
if (runningCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningCalls.add(call);
getExecutorService().execute(call); //线程池出现啦
} else {
readyCalls.add(call);
}
}
再看下 getExecutorService()取到的是一种类似于CachedThreadPool的线程池
public synchronized ExecutorService getExecutorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
2、AsyncTask
AsyncTask内部有两个线程池,一个用于任务分发,一个真正由于执行任务
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}