/**
WorkerRunnable类的构造函数
*/
private static abstract class WorkerRunnable<Params, Result> implements Callable {
// 此处的Callable也是任务;
// 与Runnable的区别:Callable存在返回值 = 其泛型
Params[] mParams;
}
/**
-
分析:FutureTask类的构造函数
-
定义:1个包装任务的包装类
-
注:内部包含Callable 、增加了一些状态标识 & 操作Callable的接口
*/
public FutureTask(Callable callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW;
}
// 回到调用原处
/**
- postResultIfNotInvoked()
*/
private void postResultIfNotInvoked()(Result result) {
// 取得任务标记
final boolean wasTaskInvoked = mTaskInvoked.get();
// 若任务无被执行,将未被调用的任务的结果通过InternalHandler传递到UI线程
if (!wasTaskInvoked) {
postResult(result);
}
}
-
创建了1个WorkerRunnable类 的实例对象 & 复写了call()方法;
-
创建了1个FutureTask类 的实例对象 & 复写了 done();
/**
- 具体使用
*/
mTask.execute();
/**
- 源码分析:AsyncTask的execute()
*/
public final AsyncTask<Params, Progress, Result> execute(Params… params) {
return executeOnExecutor(sDefaultExecutor, params);
// ->>分析1
}
/**
-
executeOnExecutor(sDefaultExecutor, params)
-
参数说明:sDefaultExecutor = 任务队列 线程池类(SerialExecutor)的对象
*/
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params… params) {
// 判断 AsyncTask 当前的执行状态
// PENDING = 初始化状态
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)”);
}
}
// 将AsyncTask状态设置为RUNNING状态
mStatus = Status.RUNNING;
// 主线程初始化工作
onPreExecute();
// 添加参数到任务中
mWorker.mParams = params;
// 执行任务
// 此处的exec = sDefaultExecutor = 任务队列 线程池类(SerialExecutor)的对象
exec.execute(mFuture);
return this;
}
/**
-
exec.execute(mFuture)
-
说明:属于任务队列 线程池类(SerialExecutor)的方法
*/
private static class SerialExecutor implements Executor {
// SerialExecutor = 静态内部类
// 即 是所有实例化的AsyncTask对象公有的
// SerialExecutor 内部维持了1个双向队列;
// 容量根据元素数量调节
final ArrayDeque mTasks = new ArrayDeque();
Runnable mActive;
// execute()被同步锁synchronized修饰
// 即说明:通过锁使得该队列保证AsyncTask中的任务是串行执行的
// 即 多个任务需1个个加到该队列中;然后 执行完队列头部的再执行下一个,以此类推
public synchronized void execute(final Runnable r) {
// 将实例化后的FutureTask类 的实例对象传入
// 即相当于:向队列中加入一个新的任务
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
// 若当前无任务执行,则去队列中取出1个执行
if (mActive == null) {
scheduleNext();
}
}
//
protected synchronized void scheduleNext() {
// 取出队列头部任务
if ((mActive = mTasks.poll()) != null) {
// 执行取出的队列头部任务
// 即调用执行任务线程池类(THREAD_POOL_EXECUTOR)
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
-
执行任务前,通过 任务队列 线程池类(SerialExecutor)将任务按顺序放入到队列中;
-
通过同步锁修饰execute()从而保证AsyncTask中的任务是串行执行的;
-
之后的线程任务执行是 通过任务线程池类(THREAD_POOL_EXECUTOR) 进行的;
3、THREAD_POOL_EXECUTOR.execute()
/**
-
源码分析:THREAD_POOL_EXECUTOR.execute()
-
说明:
-
a. THREAD_POOL_EXECUTOR实际上是1个已配置好的可执行并行任务的线程池
-
b. 调用THREAD_POOL_EXECUTOR.execute()实际上是调用线程池的execute()去执行具体耗时任务
-
c. 而该耗时任务则是步骤2中初始化WorkerRunnable实例对象时复写的call()
-
注:下面先看任务执行线程池的线程配置过程,看完后请回到步骤2中的源码分析call()
*/
// 参数设置
//获得当前CPU的核心数
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
//设置线程池的核心线程数2-4之间,但是取决于CPU核数
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
//设置线程池的最大线程数为 CPU核数*2+1
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
//设置线程池空闲线程存活时间30s
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());
}
};
//初始化存储任务的队列为LinkedBlockingQueue 最大容量为128
private static final BlockingQueue sPoolWorkQueue =
new LinkedBlockingQueue(128);
// 根据参数配置执行任务线程池,即 THREAD_POOL_EXECUTOR
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);
// 设置核心线程池的 超时时间也为30s
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
4、call()
/**
- AsyncTask的构造函数
*/
public AsyncTask() {
// 初始化WorkerRunnable变量 = 一个可存储参数的Callable对象
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
// 添加线程的调用标识
mTaskInvoked.set(true);
Result result = null;
try {
// 设置线程的优先级
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// 执行异步操作 = 耗时操作
// 即 我们使用过程中复写的耗时任务
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);// 若运行异常,设置取消的标志
throw tr;
} finally {
// 把异步操作执行的结果发送到主线程
// 从而更新UI ->>分析1
postResult(result);
}
return result;
}
};
}
/**
- postResult(result)
*/
private Result postResult(Result result) {
@SuppressWarnings(“unchecked”)
// 创建Handler对象 ->> 源自InternalHandler类
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult(this, result));
// 发送消息到Handler中
message.sendToTarget();
return result;
}
/**
- InternalHandler类
*/
private static class InternalHandler extends Handler {
// 构造函数
public InternalHandler() {
super(Looper.getMainLooper());
// 获取的是主线程的Looper()
// 故 AsyncTask的实例创建 & execute()必须在主线程使用
}
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
// 若收到的消息 = MESSAGE_POST_RESULT
// 则通过finish() 将结果通过Handler传递到主线程
case MESSAGE_POST_RESULT:
result.mTask.finish(result.mData[0]); ->>分析3
break;
// 若收到的消息 = MESSAGE_POST_PROGRESS
// 则回调onProgressUpdate()通知主线程更新进度的操作
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
最后
我还为大家准备了一套体系化的架构师学习资料包以及BAT面试资料,供大家参考及学习
已经将知识体系整理好(源码,笔记,PPT,学习视频)
andler {
// 构造函数
public InternalHandler() {
super(Looper.getMainLooper());
// 获取的是主线程的Looper()
// 故 AsyncTask的实例创建 & execute()必须在主线程使用
}
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
// 若收到的消息 = MESSAGE_POST_RESULT
// 则通过finish() 将结果通过Handler传递到主线程
case MESSAGE_POST_RESULT:
result.mTask.finish(result.mData[0]); ->>分析3
break;
// 若收到的消息 = MESSAGE_POST_PROGRESS
// 则回调onProgressUpdate()通知主线程更新进度的操作
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
最后
我还为大家准备了一套体系化的架构师学习资料包以及BAT面试资料,供大家参考及学习
已经将知识体系整理好(源码,笔记,PPT,学习视频)
[外链图片转存中…(img-bnXCRf7B-1714670703047)]
[外链图片转存中…(img-SluyEdtm-1714670703047)]
[外链图片转存中…(img-fARvAdG0-1714670703048)]