目录
1、背景
在Android中,除了Thread扮演线程角色以外,还有AsyncTask、HandlerThread、IntentService同样可以担当起异步线程的任务,它们各自有自己的适用场景。
AsyncTask:封装了Handler和线程池,它主要是为了方便开发者在子线程中更新UI;
扫描二维码关注公众号,回复: 11194980 查看本文章HandlerThread:简化了我们创建子线程Handler的过程,简化我们线程间消息传递的过程;
IntentService:内部使用了HandlerThread,它相当于一个后台线程,单相对于Thread来说,它继承了四大组件Service,所以它的优先级会高点,不容易被系统杀死。很适合后台下载类似的任务。
2、简介
AsyncTask是一个轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行任务的进度和结果传递给主线程,并在主线程中进行更新UI的操作。
AsyncTask内部实现:使用线程池来执行异步任务,然后通过Handler来将异步任务的结果,推送到我们的UI线程。
注意:AysncTask并不适合执行一些特别耗时的操作,对于特别耗时的任务,建议使用线程池。
2.1、详解
AsyncTask是一个抽象的范型类。
Params:表示参数的类型;
Progres:表示后台任务的执行进度的类型;
Result:表示后台任务返回的结果。
Async提供了四个主要的方法。除了doInBackground()方法在异步线程外,其他的三个方法都在主线程中。
2.2、使用
这里我们继承实现了AsyncTask,然后传入1、2、3三个int值,然后在异步线程池中进行相加,并且每次睡眠3秒,最后将和传到我们的UI线程,看最后的输出结果,我们也能看到只有doInBackground()在异步的线程池中执行。其余的方法都在UI线程中。
public class Test_My_AsyncTask extends AsyncTask<Integer, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
log("onPreExecute.准备");
}
@Override
protected String doInBackground(Integer... integers) {
int add = 0;
for (Integer i : integers) {
publishProgress(i);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
add = add + i;
log("doInBackground.add=" + add);
}
String result = "参数之和=" + add;
return result;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
for (Integer i : values) {
log("onProgressUpdate.进度:" + i);
}
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
log("onPostExecute.结果:" + s);
}
private void log(String msg) {
Log.e("Test_AsyncTask",String.format("%tr", new Date()) + ": "
+ Thread.currentThread().getName() + ": " + msg);
}
}
----------------------调用---------------------------------
Test_AsyncTask test =new Test_AsyncTask()
test.execute(1, 2, 3)
-----------------------结果---------------------------------
3、源码详解
从上面的使用来看,我们运行Test_My_AsyncTask的时候,只需要new出来Test_My_AsyncTask对象,然后执行它的execute()方法。
那么我们首先看一下AsyncTask的构造函数都做了什么操作?
3.1、new AsyncTask()
看下图:
当我们new 一个AsyncTask对象的时候:
1、我们会创建一个主线程的Handler;
2、我们的doInBackground()函数会被放在一个类似线程的执行对象Runnable中;
3、然后我们的doInBackground()函数返回的结果会通过Handler发送到主线程中,并且调用onPostExecute()函数。
4、当然到现在,onPostExecute()还没有被执行,因为我们还没有diao
注意:如果你想要了解Callback 和FutureTask,可以进入这个连接了解一下,如果不想了解,可以把它们当成Runnable也行。
3.2、execute()
execute()的执行:
1、会先调用onPreExecute();
2、sDefaultExecutor线程池会执行我们前面类似Runnable的FutureTask对象,这样就会执行doInBackground()方法。
3、而且在sDefaultExecutor线程池中,我们的doInBackground()并没有执行,只是被添加到一个ArrayDeque中,真正执行该任务的是THREAD_POOL_EXECUTOR线程池。
4、这样我们整个流程就算完成了。
注意:从ArrayDeque来看,默认情况,我们的AsyncTask是串行执行的。
4、手写代码
Async类
package com.yobo.yo_android.test_AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import java.util.ArrayDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class AsyncTask<Params, Progress, Result> {
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
private final WorkerRunnable<Params, Result> mWorker;
private final FutureTask<Result> mFuture;
private final Handler mHandler;
private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
public AsyncTask() {
mHandler = new InternalHandler(Looper.getMainLooper());
mWorker = new WorkerRunnable<Params, Result>() {
@Override
public Result call() {
mTaskInvoked.set(true);
Result result = doInBackground(mParams);
postResult(result);
return result;
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
super.done();
try {
postResultIfNotInvoked(get());
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
}
};
}
private void postResultIfNotInvoked(Result result) {
boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
private void postResult(Result result) {
Message message = mHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<>(this, result));
message.sendToTarget();
}
@SafeVarargs
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@SafeVarargs
private final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
private static class InternalHandler extends Handler {
InternalHandler(Looper looper) {
super(looper);
}
@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;
}
}
}
private abstract static class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
private static class AsyncTaskResult<Data> {
final AsyncTask mTask;
final Data[] mData;
@SafeVarargs
AsyncTaskResult(AsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
private void finish(Result result) {
onPostExecute(result);
}
final void publishProgress(Progress... values) {
mHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<>(this, values))
.sendToTarget();
}
/**
* 运行在主线程中,doInBackground()之前就会被调用,可以做一些准备操作
*/
protected void onPreExecute() {
}
/**
* 运行在线程池中,执行异步任务的地方
*/
protected abstract Result doInBackground(Params... params);
/**
* 运行在主线程之中,可以在doInBackground()中调用publishProgress()函数来触发该方法
*/
protected void onProgressUpdate(Progress... values) {
}
/**
* 运行在主线程之中,doInBackground()返回的Result结果会被推送这里
*/
protected void onPostExecute(Result result) {
}
/**
* -------------------------线程池的创建------------------------------------------
*/
private static final Executor sDefaultExecutor = new SerialExecutor();
private static final Executor THREAD_POOL_EXECUTOR;
private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<>(128);
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "线程-Yobo-" + mCount.getAndIncrement());
}
};
/**
* CPU核心数量
*/
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CPU_COUNT - 1,
CPU_COUNT * 2 + 1, 30, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<>();
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();
}
}
synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
}
Test_My_AsyncTask
package com.yobo.yo_android.test_AsyncTask;
import java.util.Date;
import android.util.Log;
public class Test_My_AsyncTask extends AsyncTask<Integer, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
log("onPreExecute.准备");
}
@Override
protected String doInBackground(Integer... integers) {
int add = 0;
for (Integer i : integers) {
publishProgress(i);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
add = add + i;
log("doInBackground.add=" + add);
}
String result = "参数之和=" + add;
return result;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
for (Integer i : values) {
log("onProgressUpdate.进度:" + i);
}
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
log("onPostExecute.结果:" + s);
}
private void log(String msg) {
Log.e("Test_AsyncTask",String.format("%tr", new Date()) + ": "
+ Thread.currentThread().getName() + ": " + msg);
}
}