AsyncTask中的线程池
//获取当前的cpu核心数
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
//我们想在核心池中至少有2个线程,最多4个线程,更喜欢有1个小于CPU计数的CPU,以避免CPU背景饱和
//线程池核心容量
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;
//ThreadFactory 线程工厂,通过工厂方法newThread来获取新线程
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());
}
};
//静态阻塞式队列,用来存放待执行的任务,初始容量:128个
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
/**
* 可以用来并行执行任务的一个Executor
* 静态并发线程池,可以用来并行执行任务,尽管从3.0开始,AsyncTask默认是串行执行任务
* 但是我们仍然能构造出并行的AsyncTask
*/
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;
}
AsyncTask一次性并发的数量有MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1加上new LinkedBlockingQueue(128)里面的128个,是相当多的
使用了有限制数量的等待队列,又使用了默认的AbortPolicy饱和策略,说明如果正在执行执行任务的总数量超过最大线程数量加上等待队列长度的时候,后面再进来的任务将不会被执行,会抛出异常让用户去做处理。
再做一下回顾:
如果使用了DiscardPolicy,后续任务连异常都不会抛出,直接忽略掉
使用DiscardOldestPolicy,把队列里面最旧的提走,然后新的任务顶上去
使用CallerRunsPolicy,会直接就在当前线程运行了,不会再和队列里面的任务一起等待,如果在主线程执行,这是相当危险的,一般不用这个。
如果使用的是new LinkedBlockingDeque(),那么队列将无限长,只会用到核心线程那个数量去执行,也就是说核心数量是4个,最大线程数量5个,但是不会用到第5个。
ImageLoad中的线程池
/** This cache uses a single background thread to evict entries. */
final ThreadPoolExecutor executorService =
new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
用的是0个核心线程,最大是一个线程,还有new LinkedBlockingQueue(),说明这个是串行的,单线程一个个去下载图片。
线程池的封装一
使用动态代理方式创建建一个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);
线程池的封装二
package com.bourne.android_common.ThreadDemo;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 线程管理者。
*
*/
public class ThreadManager {
private static ThreadPool threadPool; // 单列的线程池对象。
/**
* 单列,线程安全
* 获取一个线程池对象
* @return
*/
public static ThreadPool getThreadPool()
{
if (threadPool == null)
{
//枷锁
synchronized (ThreadManager.class)
{
if (threadPool == null)
{
//核心线程数,等于处理器个数乘2
int corePoolSize = Runtime.getRuntime().availableProcessors()*2;
int maximumPoolSize = 10;
long keepAliveTime = 0L;
threadPool = new ThreadPool(corePoolSize, maximumPoolSize, keepAliveTime);
}
}
}
return threadPool;
}
public static class ThreadPool
{
public static ThreadPoolExecutor executor = null;
private int corePoolSize;
private int maximumPoolSize;
private long keepAliveTime = 0; // 限制线程的的最大存活时间
public ThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime)
{
super();
this.corePoolSize = corePoolSize; //核心线程数
this.maximumPoolSize = maximumPoolSize; //最大线程 ,当核心线程用完时。决定是否开启最大线程
this.keepAliveTime = keepAliveTime; //线程排队时间,
}
/**
* 线程池:就是把一堆线程放在一起来管理。 1.通过一定的管理机制。来处理线程额执行顺序 2.管理最多可以同时执行的线程数。
* 3.其他线程通过队列的形式,也就是排队的形式来管理线程的并发数。
*
* @param runnable
*/
public void execute(Runnable runnable)
{
if (runnable == null)
{
return;
}
if (executor == null)
{
executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,
TimeUnit.MILLISECONDS,// 时间单位
new LinkedBlockingQueue<Runnable>(),// 线程队列
Executors.defaultThreadFactory(),//线程工厂
new ThreadPoolExecutor.AbortPolicy());
}
// 给线程池里面添加一个线程
executor.execute(runnable);
}
}
}
使用方式
ThreadManager.getThreadPool().execute(new WorkerThread("歌曲" + i));