- 为什么使用线程池
- 1.减少内存开销,创建和销毁线程都需要耗费 cpu 资源
- 2.由于省去创建线程时间,从而提高了程序的响应速度
- 3.方便对项目中的线程进行统一管理
- java 线程池参数解析
- 1.corePoolSize :线程池的核心线程数.超时不会被回收关闭的线程
- 2.maximumSize:线程池的最大线程数.即 workQueue 排满之后,依旧有任务提交到线程池的时候.线程池会继续创建线程处理提交的任务,创建的数量不会大于 max-core
- 3.workQueue(BlockQueue<Runnable>): 所有核心线程均在工作的情况下.依旧有任务提交至线程池.线程池会将任务加入到 workQueue 中进行排队.
- 4.keepAliveTime:除核心线程外的其他线程空闲下来后的存活时间
- 5.timeUnit:存活时间的单位
- 6.threadFactory:创建线程的工厂,默认 threadFactory,开发者可自定义线程工厂
- 7.rejectedExecutionHandler:线程溢出策略,默认有四种:1.丢弃旧任务策略,将新提交的任务加入队列2.丢弃任务策略3.将任务抛回给提交任务的线程.让其自行处理 4.按照优先级丢弃任务
- 合理配置线程池
- 判断依据
- 1.任务的执行时长:长,中,短
- 2.执行任务优先级:高,中,低
- 3.执行任务的依赖性.即任务的执行是否依赖其他资源,如数据库
- 4.业务类型:cpu 密集操作类型.IO 密集操作类型,二者混合型
- 常用配置
- 1.业务为cpu 密集操作类型
- 一般cpu 密集型的业务一般需要进行大量的计算任务.此时创建的 corePoolSize 为cpu 个数即 Runtime.getRuntime().availableProcessors
- 2.业务为IO密集操作类型
- IO 密集型的业务一般需要大量的线程进行文件读写操作,并且线程不会一直执行.此时创建的 corePoolSize 为 cpu 个数的 2 倍
- 3.业务为混合型
- 混合型的业务,尽量分开处理两种业务操作,即配置两个线程池
- 1.业务为cpu 密集操作类型
- 判断依据
- 线程池工作总结
- 当有任务提交到线程池中时.线程池优先创建corePoolSize 数量之内的线程进行任务处理.调用
- 如果线程数已经达到 corePoolSize,并且没有空闲线程时.任务会提交到 BlockQueue 队列中.等待任务的执行.
- 如果BlockQueue 队列已经满了.线程池则创建总线程数小于 maximumPoolSize的线程,进行任务处理
- 如果线程池总线程数已经达到maximumPoolSize 数.该任务则执行 rejectedExecutionHandler 机制.如抛弃任务等
- AsyncTask 源码解析
- 使用 AsyncTask时,一般会覆写以下几个方法以及调用其 execute(Object[] params) 方法
- onPreExecute() 在 UI 线程中调用
- doInBackground(Object[] params) 在子线程中异步调用
- onProgressUpdate(Object value) 在UI 线程中调用,通过在异步线程方法中调用 publishProgress()来回调该方法
- onPostExecute(Object resule) 在 UI 线程中调用.返回异步线程任务结果
下面来看一下覆写的各个方法的调用时机
- 构造函数中初始化 WorkRunnable 实例 mWork.WorkRunnable 为Callable 派生类,call方法中调用 doInBackGround()方法,并将其返回结果传入 postResult()方法中,postResult 返回值作为 call 方法的返回值
- 构造函数中初始化 FutureTask 实例.并将mWork传入,当mWork任务完成时 .调用 postResultIfNotInvoked(get()),其中get() 返回值为mWork 的 call()方法返回值.
public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() { //WorkRunnable为 Callable 派生类 public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked 异步方法调用处 Result result = doInBackground(mParams); Binder.flushPendingCommands(); return postResult(result);//返回结果为 doInBackground 方法结果 } }; mFuture = new FutureTask<Result>(mWorker) { //初始化 FutureTask ,yu @Override protected void done() { try { postResultIfNotInvoked(get());//通知异步任务执行结束 } catch (InterruptedException e) { android.util.Log.w(LOG_TAG, e); } catch (ExecutionException e) { throw new RuntimeException("An error occurred while executing doInBackground()", e.getCause()); } catch (CancellationException e) { postResultIfNotInvoked(null); } } }; }
- postResultIfNotInvoked()->postResult().postResult()方法中使用 Handler 机制,通知 UI 线程,进行 onPostExecute(Object result)回调
/**
*使用 InternalHandler.将异步任务运行结果通知到 UI 线程
*/
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
/**
*使用 InternalHandler.在 UI 线程处理子线程回传的结果
*/
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT: // 接收并处理异步任务返回的结果
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
接下来看一下构造函数的 mFuture 是何时执行的,使用 AsyncTask 时,实例化之后需要调用其 execute()方法,才可执行 doInBackground()中的异步任务,由此,可看一下 execute()方法的实现
- execute(Object[] params)
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
- executeOnExecutor(Executor exec,Object[] params),在executeOnExecutor()方法中,调用了 onPreExecute()方法,赋值了异步任务的参数,并在传入的线程池中执行了 mFuture 任务
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
mStatus = Status.RUNNING;
onPreExecute();//在 UI 线程中处理执行异步任务之前需要做的工作
mWorker.mParams = params; //赋值 doInBackground 执行时所需要的参数
exec.execute(mFuture); //线程池执行 mFuture
return this;
}
- 被传入的 线程池 exec为静态变量 sDefaultExecutor . 实际为 SerialExecutor 的实例,SerialExecutor 中,创建了双端队列 ArrayDeque<Runnable>,在线程池执行方法中,将提交的FutureTask包装为 Runnable 实例并且推进双端队列的队末,同时取出双端队列的队头任务,放入THREAD_POOL_EXECUTOR线程池中执行,队列中任务执行完之后又会去队列中取下一个需要执行的任务
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
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);
}
}
}
- THREAD_POOL_EXECUTOR 静态线程池,具体配置如下:
private static final int CPU_COUNT =
Runtime.getRuntime().availableProcessors();//此处为获取设备cpu 核心数
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE = 1;
/**
* 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);
- 总结:
- 线程池的创建 : AsyncTask 初始化时就创建了两个线程池.SerialExecutor 和 ThreadPoolExecutor.SerialExecutor 是将 AsyncTask 需要执行的任务包装并串行放到 ThreadPoolExecutor 中执行的.即 SerialExecutor 是将任务串行化的,真正执行任务的线程池的是 ThreadPoolExecutor,而且这两个线程池创建的是静态的.也就是说无论实例化多少个 AsyncTask所用的线程池只有这两个
- 任务的执行: 任务的执行是在 execute()方法中.执行过 run()方法后,会调用 scheduleNext()方法,继续在双端队列中取下一个任务放进 ThreadPoolExecutor 中执行.知道队列为空为止
- 消息的传递: AsyncTask 是依靠 Handler 来进行消息传递的.其中为了一个 InternalHandler 派生自 Handler 的子类,在任务执行结束后.通过 InternalHandler 实例将 doInBackground()返回值通知到 UI 线程.其 handleMessage 方法中进行onPostExecute(Object result)回调.另外需要进行异步任务进度通知的时候.会在异步任务中调用 publishProgress(Object value)方法,也是通过 Handler 来切换到 UI 线程进行 onProgressUpdate()方法回调的
- 使用 AsyncTask 的注意事项: 同一AsyncTask实例的 execute()方法只能调用一次,否则会抛出IllegalStateException 异常,如果需要调用多次则每次调用都需要实例化新的 AsyncTask 对象
- AsyncTask 的优缺点:
- 优点:AsyncTask 是轻量级的异步任务处理类.使用起来方便.代码简介.可以使用 cancle() 方法来取消任务
- 缺点:不适合执行运行时间过长的任务和任务数过多的情况.此时会有多线程的控制问题.当处理多个异步任务的时候.UI 线程更新变得困难