线程池的好处
(1)重用线程池中的线程,避免因为线程的创建和销毁所带来的性能的开销。
(2)能有效控制线程池的最大并发数,避免线程间因抢占系统资源而导致线程阻塞。
(3)能够对线程进行管理,并提供定时执行及指定间隔循环执行等功能
线程池的配置
ThreadPoolExecutor是线程池的正真实现
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory)
corePoolSize
线程池的核心线程数,默认情况下,核心线程在线程池中一直存活。如果将ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true,那么闲置的核心线程会有超时策略,这个时间由keepAliveTime所指定,当时间超过keepAliveTime所指定的时间后,核心线程就会被终止。
maximumPoolSize
线程池所能容纳的最大线程数,当活动线程数达到这个值后,后续任务将会被阻塞。
keepAliveTime
非核心线程闲置时的超时时长,超过这个时间,非核心线程就会被回收。如果将ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true,keepAliveTime同样会作用于核心线程
unit
keepAliveTime参数的时间单位,是一个枚举类型,常用的有TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)、TimeUnit.MINUTES(分钟)等
BlockingQueue<Runnable> workQueue
线程池中的任务队列,通过线程池的execute方法提交的Runnable对象存储在这个参数中。
threadFactory
线程工厂,为线程池提供创建线程的功能。ThreadFactory是一个接口,只有一个方法 Thread new Thread(Runnable runnable)
ThreadPoolExecutor执行任务时的规则:
(1)如果线程池中的线程数量未达到核心线程的数量,那么会直接启动一个核心线程来执行任务。
(2)如果线程池中的线程数量已达到或者超过核心线程的数量,那么任务会被插入到任务队列中排队等待执行。
(3)如果无法将任务插入任务队列中(任务队列已满),这时候如果线程池中的线程数量未达到线程池规定的最大值,那么会立刻启动一个非核心线程来执行任务。
ThreadPoolExecutor在AsyncTask中的配置
用于AsyncTask封装了线程池,我们从AsyncTask源码中可以看出AsyncTask对ThreadPoolExecutor的配置
public abstract class AsyncTask<Params, Progress, Result>
{
private static final String LOG_TAG = "AsyncTask";
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
/**
* An {@link Executor} that can be used to execute tasks in parallel.
*/
public static final Executor THREAD_POOL_EXECUTOR;
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;
}
线程池的分类
Android中四类具有不同功能特征的线程池,它们都直接或者间接地通过配置ThreadPoolExecutor来实现自己的功能特性
FixedThreadPool
通过Executors的newFixedThreadPool来创建
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
是一种线程数量固定的线程池,当线程处于空闲状态时,不会被回收,当所有线程都处于活动状态时,新任务将处于等待状态,直到有线程空闲出来。FixedThreadPool中只有核心线程并且核心线程没有超时限制
newCachedThreadPool
通过Executors的newCachedThreadPool来创建
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}
可以看出它没有核心线程,线程数量不定Integer.MAX_VALUE,超时时长为60秒,比较适合执行大量的耗时较少的任务。
ScheduledThreadPool
通过Executors的newScheduledThreadPool来创建
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
核心线程数量是固定的,非核心线程的数量没有限制,并且非核心线程闲置时会被立即回收。主要用于执行定时任务和具有固定周期的重复任务。
SingleThreadExecutor
通过Executors的newSingleThreadExecutor来创建
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
只有一个核心线程,它确保所有的任务都在同一个线程中按顺序执行。不需要处理线程同步的问题。