线程是操作系统调度的最小单元
线程是一种受限的系统资源,不可能无限制的产生,线程创建和销毁都会有相应开销。
线程池缓存一定数量的线程,避免频繁创建和销毁线程带来的系统开销。
Android中线程池,是通过 Executor 派生特定类型的线程池。
一、AsyncTask的使用和注意事项
public abstract class AsyncTask<Params, Progress, Result> {
}
1、参数
AsyncTask 是轻量级的异步任务类,在线程池中执行后台任务
把执行的 进度、结果 传递给主线程。
内部封装了 线程池 、 MainHandler
参数一:Params 参数的类型
参数二:Progress 后台任务的执行进度的类型
参数三:Result 后台任务的返回结果类型
如果AsyncTask 不需要传递具体参数,者三个泛型参数可以用Void代替。
2、限制
1)AsyncTask 的 类要在主线程中加载(android 4.1 以上版本中系统自动完成)
2)AsyncTask 对象必须在 主线程 创建
3)execute 方法必须在 主线程 调用
4)不要在程序中直接调用 onPreExecute()、onPostExecute()、doInBackgound()、onProgressUpdate
AsyncTask 内部调用的
5)一个AsyncTask 对象 只能执行一次,只能 调一次execute 方法,否则会报运行时异常
6) android 1.6 之后 AsyncTask 采用线程池处理并行任务。
二、AsyncTask几个重要的方法
doInBackgound、onProgressUpdate、onPostExecute等
1、onPreExecute()
任务执行之前,在 主线程 回调,用于做一些准备工作。
2、doInBackgound(Params… params)
线程池中执行,params 表示入参
在此方法中,通过 publishProgress 方法更新任务进度,
publishProgress 方法,会调用 onProgressUpdate 方法,
doInBackgound 方法,返回计算结果给 onPostExecute 方法
3、onProgressUpdate(Progress… values)
执行进度改变时,在主线程回调
4、onPostExecute(Result result)
任务执行完成,在主线程中回调,result 参数是后台任务返回值。
5、onCanceled()
任务被取消时,在主线程回调,此时 onPostExecute 不会被调用。
6、 使用
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
@Override
protected Long doInBackgound(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
//更新进度
publishProgress((int) ((i / (float) count) * 100));
if(isCancelled()) {
break;
}
}
return totalSize;
}
@Override
protected void onProgressUpdate(Integer... progress) {
//更新UI
setProgressPercent(progress[0]);
}
@Override
protected void onPostExecute(Long result) {
//结果处理
showDialog("Downloaded " + result + " bytes")
}
}
new DownloadFilesTask().execute(url1, url2, url3);
三、AsyncTask的工作原理
任务队列容量为 128
AsyncTask 先将任务塞入队列,再用线程池执行任务,
执行时通过publishProgress 更新进度到主线程
执行完成后结果回调主线程返回结果
AsyncTask 有 mStatus字段记录状态,每个 AsyncTask 只能执行一次 execute 方法
public abstract class AsyncTask<Params, Progress, Result> {
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;
//任务队列容量为 128
private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128);
//用于执行任务的线程池
public static final Executor THREAD_POOL_EXECUTOR;
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, //核心线程数:CPU核心数-1 并且最少为2,最大为4
MAXIMUM_POOL_SIZE, //最大线程数:CPU核心数*2+1
KEEP_ALIVE_SECONDS, //闲置时间30秒
TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
//用于排队任务
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
//用于将执行环境从线程池切换到主线程
private final Handler mHandler;
//一个串行的线程池,添加的任务会放到一个队列中,按顺序执行。
SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
//把要执行的任务,塞到 mTasks 队列中
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);
}
}
}
public AsyncTask(@Nullable Looper callbackLooper) {
// 绑定主线程的 Handler
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
...
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
...
try {
//线程池中执行 doInBackgound()
//noinspection unchecked
result = doInBackground(mParams);
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
//执行完后,发消息,通知主线程,执行 AsyncTask.finish()方法
postResult(result);
}
...
return result;
}
};
mFuture = new FutureTask<Result>(mWorker) {
@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);
}
}
};
}
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
//Handler 在主线程收到消息后,会执行 finish() 方法
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
/* sDefaultExecutor 是一个串行的线程池,
* 一个进程中所有的AsyncTask,都在这个串行的线程池中排队执行
*/
return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread //主线程中执行
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) {
if (mStatus != Status.PENDING) {//一个 AsyncTask对象,只能执行一次
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();
mWorker.mParams = params;
//调用线程池执行异步任务
exec.execute(mFuture);
return this;
}
}
推荐阅读:
《Android开发艺术探索》第十一章 Android的线程和线程池
《Java并发编程的艺术》第九章 Java中的线程池,第十章 Executor框架