线程池的优点:
- 重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。
- 能有效控制线程池的最大并发数,避免大量的线程之间因相互抢占系统资源而导致的堵塞线程。
- 能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能。
- 相对于AsyncTask来说,最大的优势在于:线程可控!比如在离开了某个页面,提交到AsyncTask不能的任务不能撤销,线程池可以在不需要的时候将某个线程移除。
ThreadPoolExecutor的介绍
Android中的线程池概念来源于Java中的Executor,Executor是一个接口,真正的线程池的实现为ThreadPoolExecutor。ThreadPoolExecutor提供了一系列参数来配置线程池,通过不同的参数可以创建不同的线程池。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
-
corePoolSize:核心线程数
默认核心线程会在线程池中一直存活,即使它们处于闲置状态。可以通过设置ThreadPoolExecutor的allowCoreThreadTimeOut为true,当超过一定的闲置时间,将关闭核心池,这个时间间隔由keepAliveTime所制定。
-
maximumPoolSize:最大线程数
当活动线程数达到这个数值后,后续的新任务将会被阻塞。
-
keepAliveTime:非核心线程时超过时长
超过这个时长,非核心池将会被回收。当设置allowCoreThreadTimeOut为true时,同样会作用于核心线程。
-
unit 时间单位
-
workQueue:任务队列
通过线程池execute方法提交的Runnable对象会被存储在这个参数中。
-
threadFactory:线程工厂
为线程池提供创建新线程的功能。 ThreadFactory只是一个接口,它只有一个方法:Thread new Thread(Runnable r).
典型的线程池配置
-
AsyncTask中的线程池配置:
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 1;
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>(10);
/**
* An {@link Executor} that can be used to execute tasks in parallel.
*/
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
在不同的android本版本中,AsyncTask的线程池不同,但都大同小异,在另一个版本中的AsyncTask中是使用的CPU核心数为标准来给定核心线程数和最大线程数。
-
ImageLoad中的线程池:
/** This cache uses a single background thread to evict entries. */
final ThreadPoolExecutor executorService =
new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
android中提供的一些线程池:
singleTaskExecutor = Executors.newSingleThreadExecutor();// 每次只执行一个线程任务的线程池
limitedTaskExecutor = Executors.newFixedThreadPool(3);// 限制线程池大小为7的线程池
allTaskExecutor = Executors.newCachedThreadPool(); // 一个没有限制最大线程数的线程池
scheduledTaskExecutor = Executors.newScheduledThreadPool(3);// 一个可以按指定时间可周期性的执行的线程池
scheduledTaskFactoryExecutor = Executors.newFixedThreadPool(3, new ThreadFactoryTest());// 按指定工厂模式来执行的线程池
scheduledTaskFactoryExecutor.submit(new Runnable()
{
@Override
public void run()
{
Log.i("KKK", "This is the ThreadFactory Test submit Run! ! ! ");
}
});
线程池的案例:
使用动态代理方式创建建一个ThreadPoolProxyFactory ,里面提供两种方式获取线程池:普通线程池和下载的线程池。
public class ThreadPoolProxyFactory {
static ThreadPoolProxy mNormalThreadPoolProxy;
static ThreadPoolProxy mDownLoadThreadPoolProxy;
/**
* 得到普通线程池代理对象mNormalThreadPoolProxy
*/
public static ThreadPoolProxy getNormalThreadPoolProxy() {
if (mNormalThreadPoolProxy == null) {
synchronized (ThreadPoolProxyFactory.class) {
if (mNormalThreadPoolProxy == null) {
mNormalThreadPoolProxy = new ThreadPoolProxy(5, 5);
}
}
}
return mNormalThreadPoolProxy;
}
/**
* 得到下载线程池代理对象mDownLoadThreadPoolProxy
*/
public static ThreadPoolProxy getDownLoadThreadPoolProxy() {
if (mDownLoadThreadPoolProxy == null) {
synchronized (ThreadPoolProxyFactory.class) {
if (mDownLoadThreadPoolProxy == null) {
mDownLoadThreadPoolProxy = new ThreadPoolProxy(3, 3);
}
}
}
return mDownLoadThreadPoolProxy;
}
}
线程池代理,替线程池完成一些操作。提供了三种方法:执行任务,提交任务,移除任务。
public class ThreadPoolProxy {
ThreadPoolExecutor mExecutor;
private int mCorePoolSize;
private int mMaximumPoolSize;
/**
* @param corePoolSize 核心池的大小
* @param maximumPoolSize 最大线程数
*/
public ThreadPoolProxy(int corePoolSize, int maximumPoolSize) {
mCorePoolSize = corePoolSize;
mMaximumPoolSize = maximumPoolSize;
}
/**
* 初始化ThreadPoolExecutor
* 双重检查加锁,只有在第一次实例化的时候才启用同步机制,提高了性能
*/
private void initThreadPoolExecutor() {
if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) {
synchronized (ThreadPoolProxy.class) {
if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) {
long keepAliveTime = 3000;
TimeUnit unit = TimeUnit.MILLISECONDS;
BlockingQueue<Runnable> workQueue = new LinkedBlockingDeque<>();
ThreadFactory threadFactory = Executors.defaultThreadFactory();
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
mExecutor = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, handler);
}
}
}
}
/**
执行任务和提交任务的区别?
1.有无返回值
execute->没有返回值
submit-->有返回值
2.Future的具体作用?
1.有方法可以接收一个任务执行完成之后的结果,其实就是get方法,get方法是一个阻塞方法
2.get方法的签名抛出了异常===>可以处理任务执行过程中可能遇到的异常
*/
/**
* 执行任务
*/
public void execute(Runnable task) {
initThreadPoolExecutor();
mExecutor.execute(task);
}
/**
* 提交任务
*/
public Future<?> submit(Runnable task) {
initThreadPoolExecutor();
return mExecutor.submit(task);
}
/**
* 移除任务
*/
public void remove(Runnable task) {
initThreadPoolExecutor();
mExecutor.remove(task);
}
}
具体使用:
- 普通线程的使用:
ThreadPoolProxyFactory.getNormalThreadPoolProxy().execute(Runnable);
- 下载线程的使用:
ThreadPoolProxyFactory.getDownLoadThreadPoolProxy().execute(downLoadTask);
ThreadPoolProxyFactory.getDownLoadThreadPoolProxy().remove(downLoadInfo.downLoadTask);