package com.example.demo.activity.net;

import java.util.ArrayDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
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.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.os.Process; public abstract class MyAsyncTask<Params, Progress, Result> {
private static final String LOG_TAG = "AsyncTask";
// 返回cpu的数目
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// 设置核心线程数量
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;
// 创建线程的工厂
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());
}
}; private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128); // 创建了一个线程池,传入参数为核心线程2,最多线程3,休息时间1秒,容纳128个线程对象的队列,线程工厂
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
// 创建一个串行执行任务对象
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
// handler接受码
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
// handler对象
private static final InternalHandler sHandler = new InternalHandler();
// 默认使用串行执行
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
// 继承了一个泛型的回掉接口,在mFuture的run方法中会调用mWorker的call回调方法
private final WorkerRunnable<Params, Result> mWorker;
// 线程对象,实现了RunnableFuture接口
private final FutureTask<Result> mFuture; private volatile Status mStatus = Status.PENDING;
// 判断是否已经主动取消执行中的任务
private final AtomicBoolean mCancelled = new AtomicBoolean();
// 判断
private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); // 判断是否正常调用postResult(doInBackground(mParams))
private static class SerialExecutor implements Executor {
// 维护的队列,每execute一次就offer进来一个mFuture线程对象
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive; public synchronized void execute(final Runnable r) {
// 默认的execute提交就是把封装的mFuture用该方法提交,所有提交的线程对象都先存放在该队列中
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
// 队列中所有线程对象都执行完之后,mActive = mTasks.poll()就会等于null
// 然后新加入的任务又会重新启动执行
if (mActive == null) {
scheduleNext();
}
} // 从队列中获取一个线程对象,将他放到线程池中执行,执行完之后就会接着调用scheduleNext()来执行队列中的下一个线程对象
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
} /**
* Indicates the current status of the task. Each status will be set only once during the lifetime of a task.
*/
public enum Status {
/**
* Indicates that the task has not been executed yet.
*/
PENDING,
/**
* Indicates that the task is running.
*/
RUNNING,
/**
* Indicates that {@link AsyncTask#onPostExecute} has finished.
*/
FINISHED,
} /** @hide Used to force static handler to be created. */
public static void init() {
sHandler.getLooper();
} /**
* 设置默认的线程池
*
* @param exec
*/
public static void setDefaultExecutor(Executor exec) {
sDefaultExecutor = exec;
} /**
* 构造函数,初始化了mFuture线程对象,并封装了mWorker回调接口
*/
public MyAsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true); Process.setThreadPriority(10);
// noinspection unchecked
return postResult(doInBackground(mParams));
}
};
// 被强行打断,出异常,或者正常结束都会调用下面的done(),
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 occured while executing doInBackground()", e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
} // 正常结束,出异常,被强行打断就会调用下面的方法
// 但是正常结束不会调用里面的postResult(result)。因为他已经在call()中调用
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
} /**
* 使用handler往主线程中发送返回结果
*
* @param result
* @return
*/
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
} /**
* Returns the current status of this task.
*
* @return The current status.
*/
public final Status getStatus() {
return mStatus;
} /**
* Override this method to perform a computation on a background thread. The specified parameters are the parameters passed to {@link #execute} by the caller of this task.
*
* This method can call {@link #publishProgress} to publish updates on the UI thread.
*
* @param params
* The parameters of the task.
*
* @return A result, defined by the subclass of this task.
*
* @see #onPreExecute()
* @see #onPostExecute
* @see #publishProgress
*/
protected abstract Result doInBackground(Params... params); /**
* Runs on the UI thread before {@link #doInBackground}.
*
* @see #onPostExecute
* @see #doInBackground
*/
protected void onPreExecute() {
} /**
* <p>
* Runs on the UI thread after {@link #doInBackground}. The specified result is the value returned by {@link #doInBackground}.
* </p>
*
* <p>
* This method won't be invoked if the task was cancelled.
* </p>
*
* @param result
* The result of the operation computed by {@link #doInBackground}.
*
* @see #onPreExecute
* @see #doInBackground
* @see #onCancelled(Object)
*/
@SuppressWarnings({ "UnusedDeclaration" })
protected void onPostExecute(Result result) {
} /**
* Runs on the UI thread after {@link #publishProgress} is invoked. The specified values are the values passed to {@link #publishProgress}.
*
* @param values
* The values indicating progress.
*
* @see #publishProgress
* @see #doInBackground
*/
@SuppressWarnings({ "UnusedDeclaration" })
protected void onProgressUpdate(Progress... values) {
} /**
* <p>
* Runs on the UI thread after {@link #cancel(boolean)} is invoked and {@link #doInBackground(Object[])} has finished.
* </p>
*
* <p>
* The default implementation simply invokes {@link #onCancelled()} and ignores the result. If you write your own implementation, do not call <code>super.onCancelled(result)</code>.
* </p>
*
* @param result
* The result, if any, computed in {@link #doInBackground(Object[])}, can be null
*
* @see #cancel(boolean)
* @see #isCancelled()
*/
@SuppressWarnings({ "UnusedParameters" })
protected void onCancelled(Result result) {
onCancelled();
} /**
* <p>
* Applications should preferably override {@link #onCancelled(Object)}. This method is invoked by the default implementation of {@link #onCancelled(Object)}.
* </p>
*
* <p>
* Runs on the UI thread after {@link #cancel(boolean)} is invoked and {@link #doInBackground(Object[])} has finished.
* </p>
*
* @see #onCancelled(Object)
* @see #cancel(boolean)
* @see #isCancelled()
*/
protected void onCancelled() {
} /**
* Returns <tt>true</tt> if this task was cancelled before it completed normally. If you are calling {@link #cancel(boolean)} on the task, the value returned by this method should be checked
* periodically from {@link #doInBackground(Object[])} to end the task as soon as possible.
*
* @return <tt>true</tt> if task was cancelled before it completed
*
* @see #cancel(boolean)
*/
public final boolean isCancelled() {
return mCancelled.get();
} /**
* <p>
* Attempts to cancel execution of this task. This attempt will fail if the task has already completed, already been cancelled, or could not be cancelled for some other reason. If successful, and
* this task has not started when <tt>cancel</tt> is called, this task should never run. If the task has already started, then the <tt>mayInterruptIfRunning</tt> parameter determines whether the
* thread executing this task should be interrupted in an attempt to stop the task.
* </p>
*
* <p>
* Calling this method will result in {@link #onCancelled(Object)} being invoked on the UI thread after {@link #doInBackground(Object[])} returns. Calling this method guarantees that
* {@link #onPostExecute(Object)} is never invoked. After invoking this method, you should check the value returned by {@link #isCancelled()} periodically from {@link #doInBackground(Object[])} to
* finish the task as early as possible.
* </p>
*
* @param mayInterruptIfRunning
* <tt>true</tt> if the thread executing this task should be interrupted; otherwise, in-progress tasks are allowed to complete.
*
* @return <tt>false</tt> if the task could not be cancelled, typically because it has already completed normally; <tt>true</tt> otherwise
*
* @see #isCancelled()
* @see #onCancelled(Object)
*/
/**
* 外部强行打断任务执行的时候调用,正常结束不用调用
*
* @param mayInterruptIfRunning
* @return
*/
public final boolean cancel(boolean mayInterruptIfRunning) {
mCancelled.set(true);
return mFuture.cancel(mayInterruptIfRunning);
} /**
* Waits if necessary for the computation to complete, and then retrieves its result.
*
* @return The computed result.
*
* @throws CancellationException
* If the computation was cancelled.
* @throws ExecutionException
* If the computation threw an exception.
* @throws InterruptedException
* If the current thread was interrupted while waiting.
*/
public final Result get() throws InterruptedException, ExecutionException {
return mFuture.get();
} /**
* Waits if necessary for at most the given time for the computation to complete, and then retrieves its result.
*
* @param timeout
* Time to wait before cancelling the operation.
* @param unit
* The time unit for the timeout.
*
* @return The computed result.
*
* @throws CancellationException
* If the computation was cancelled.
* @throws ExecutionException
* If the computation threw an exception.
* @throws InterruptedException
* If the current thread was interrupted while waiting.
* @throws TimeoutException
* If the wait timed out.
*/
public final Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return mFuture.get(timeout, unit);
} /**
* Executes the task with the specified parameters. The task returns itself (this) so that the caller can keep a reference to it.
*
* <p>
* Note: this function schedules the task on a queue for a single background thread or pool of threads depending on the platform version. When first introduced, AsyncTasks were executed serially
* on a single background thread. Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting
* {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are back to being executed on a single thread to avoid common application errors caused by parallel execution. If you truly want parallel
* execution, you can use the {@link #executeOnExecutor} version of this method with {@link #THREAD_POOL_EXECUTOR}; however, see commentary there for warnings on its use.
*
* <p>
* This method must be invoked on the UI thread.
*
* @param params
* The parameters of the task.
*
* @return This instance of AsyncTask.
*
* @throws IllegalStateException
* If {@link #getStatus()} returns either {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
*
* @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
* @see #execute(Runnable)
*/
/**
* 使用默认的串行执行
*
* @param params
* @return
*/
public final MyAsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
} /**
* Executes the task with the specified parameters. The task returns itself (this) so that the caller can keep a reference to it.
*
* <p>
* This method is typically used with {@link #THREAD_POOL_EXECUTOR} to allow multiple tasks to run in parallel on a pool of threads managed by AsyncTask, however you can also use your own
* {@link Executor} for custom behavior.
*
* <p>
* <em>Warning:</em> Allowing multiple tasks to run in parallel from a thread pool is generally <em>not</em> what one wants, because the order of their operation is not defined. For example, if
* these tasks are used to modify any state in common (such as writing a file due to a button click), there are no guarantees on the order of the modifications. Without careful work it is possible
* in rare cases for the newer version of the data to be over-written by an older one, leading to obscure data loss and stability issues. Such changes are best executed in serial; to guarantee
* such work is serialized regardless of platform version you can use this function with {@link #SERIAL_EXECUTOR}.
*
* <p>
* This method must be invoked on the UI thread.
*
* @param exec
* The executor to use. {@link #THREAD_POOL_EXECUTOR} is available as a convenient process-wide thread pool for tasks that are loosely coupled.
* @param params
* The parameters of the task.
*
* @return This instance of AsyncTask.
*
* @throws IllegalStateException
* If {@link #getStatus()} returns either {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
*
* @see #execute(Object[])
*/
/**
* 可以使用该类里面提供的线程池来执行任务
*
* @param exec
* @param params
* @return
*/
public final MyAsyncTask<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(); mWorker.mParams = params;
exec.execute(mFuture); return this;
} /**
* Convenience version of {@link #execute(Object...)} for use with a simple Runnable object. See {@link #execute(Object[])} for more information on the order of execution.
*
* @see #execute(Object[])
* @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
*/
/**
* 使用默认的串行来执行线程对象
*
* @param runnable
*/
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
} /**
* This method can be invoked from {@link #doInBackground} to publish updates on the UI thread while the background computation is still running. Each call to this method will trigger the
* execution of {@link #onProgressUpdate} on the UI thread.
*
* {@link #onProgressUpdate} will not be called if the task has been canceled.
*
* @param values
* The progress values to update the UI with.
*
* @see #onProgressUpdate
* @see #doInBackground
*/
/**
* 如果已经被取消,就不会发送更新进度条
*
* @param values
*/
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
} /**
* 在handler中判断,如果已经被取消就调用onCancelled(result),正常结束调用onPostExecute(result)
*
* @param result
*/
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
} /**
* handler对象
*
* @author liulj
*
*/
private static class InternalHandler extends Handler {
@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 static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
} /**
* handler中传递的对象
*
* @author liulj
*
* @param <Data>
*/
@SuppressWarnings({ "RawUseOfParameterizedType" })
private static class AsyncTaskResult<Data> {
final MyAsyncTask mTask;
final Data[] mData; AsyncTaskResult(MyAsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
}

AsyncTask源码解析的更多相关文章

  1. Android AsyncTask 源码解析

    1. 官方介绍 public abstract class AsyncTask extends Object  java.lang.Object    ↳ android.os.AsyncTask&l ...

  2. Android -- AsyncTask源码解析

    1,前段时间换工作的时候,关于AsyncTask源码这个点基本上大一点的公司都会问,所以今天就和大家一起来总结总结.本来早就想写这篇文章的,当时写<Android -- 从源码解析Handle+ ...

  3. Android开发——AsyncTask的使用以及源码解析

    .AsyncTask使用介绍  转载请标明出处:http://blog.csdn.net/seu_calvin/article/details/52172248 AsyncTask封装了Thread和 ...

  4. Android源码解析——AsyncTask

    简介 AsyncTask 在Android API 3引入,是为了使UI线程能被正确和容易地使用.它允许你在后台进行一些操作,并且把结果带到UI线程中,而不用自己去操纵Thread或Handler.它 ...

  5. 小白挑战:AsyncTask源码分析

    //AsyncTask从本质上讲,是对ThreadPool和handler的封装. 在学习线程池相关的知识时,看到书中提到AsyncTask的实现中使用到了ThreadPool,于是把源码翻了出来, ...

  6. Android Asynctask与Handler的比较,优缺点区别,Asynctask源码

    1  AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以 ...

  7. 【转载】Xutils3源码解析

    Github源码地址:https://github.com/wyouflf/xUtils3 原文地址 :http://www.codekk.com/blogs/detail/54cfab086c476 ...

  8. Android源码解析系列

    转载请标明出处:一片枫叶的专栏 知乎上看了一篇非常不错的博文:有没有必要阅读Android源码 看完之后痛定思过,平时所学往往是知其然然不知其所以然,所以为了更好的深入Android体系,决定学习an ...

  9. 还怕问源码?Github上神级Android三方源码解析手册,已有7.6 KStar

    或许对于许多Android开发者来说,所谓的Android工程师的工作"不过就是用XML实现设计师的美术图,用JSON解析服务器的数据,再把数据显示到界面上"就好了,源码什么的,看 ...

随机推荐

  1. Getting Started with ASP.NET Web API 2 (C#)

    By Mike Wasson|last updated May 28, 2015 7556 of 8454 people found this helpful Print   Download Com ...

  2. 原 ng-include用法分析以及多标签页面的简单实现方式

    Demo:http://webenh.chinacloudsites.cn/Default/Demo2 在平时的项目开发中,应该会经常遇到上图所示的需求,就是在一个页面中有多个标签,被选中的标签颜色会 ...

  3. Lazy<T>在Entity Framework中的性能优化实践(附源码)

    在使用EF的过程中,导航属性的lazy load机制,能够减少对数据库的不必要的访问.只有当你使用到导航属性的时候,才会访问数据库.但是这个只是对于单个实体而言,而不适用于显示列表数据的情况. 这篇文 ...

  4. Linux hostname对Oracle实例以及监听的影响

    在Linux平台中,对hostname的修改,是否对ORACLE数据库实例或监听进程有影响呢?如果有影响,又要如何解决问题呢?另外/etc/hosts下相关内容的修改,是否也会影响实例或监听呢?这里涉 ...

  5. RabbitMQ入门教程——.NET客户端使用

    众所周知RabbitMQ使用的是AMQP协议.我们知道AMQP是一种网络协议,能够支持符合要求的客户端应用和消息中间件代理之间进行通信. 其中消息代理扮演的角色就是从生产者那儿接受消息,并根据既定的路 ...

  6. IO系统性能之一:衡量性能的几个指标

    作为一个数据库管理员,关注系统的性能是日常最重要的工作之一,而在所关注的各方面的性能只能IO性能却是最令人头痛的一块,面对着各种生涩的参数和令人眼花缭乱的新奇的术语,再加上存储厂商的忽悠,总是让我们有 ...

  7. 烂泥:php5.6源码安装与apache集成

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. apache对php的支持是通过apache的mod_php5模块来支持的,这点与nginx不同.nginx是通过第三方的fastcgi处理器才可以对p ...

  8. Javascript parseFloat内部解析规则

    这是由小习发的一个问题引起的讨论,结束后大家各自加深了多parseFloat的理解. 如下 16进制数0x10使用parseFloat转成数字,结果为0.潜意识期望的结果是16. 有人说脑残,16进制 ...

  9. centos6.5编译安装lamp开发环境

    一.系统以及软件的准备 系统及编译安装包的下载地址:http://pan.baidu.com/s/1jIjqinc   密码:ghc2 说明:由于centos6.5是分卷压缩的,且压缩为三个压缩包,所 ...

  10. Semiautomated IMINT Processing Baseline System——翻译

    题目 半自动的IMINT(图像情报)处理基准系统 摘要 SAIP ACTD(半自动图像情报处理高级概念技术展示项目)的目的是,通过战略上的传感器采集,使图像成为指挥官掌控整个战场的主要源头.该采集系统 ...