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. Vector和Stack(已过时,不建议使用)

    以下内容基于jdk1.7.0_79源码: 什么是Vector和Stack Vector:线程安全的动态数组 Stack:继承Vector,基于动态数组实现的一个线程安全的栈: Vector和Stack ...

  2. Kafka 分布式的,基于发布/订阅的消息系统

    Kafka是一种分布式的,基于发布/订阅的消息系统.主要设计目标如下: 通过O(1)的磁盘数据结构提供消息的持久化,这种结构对于即使数以TB的消息存储也能够保持长时间的稳定性能. 高吞吐量:即使是非常 ...

  3. MySQL 调优基础(五) Linux网络

    1. TCP/IP模型 我们一般知道OSI的网络参考模型是分为7层:“应表会传网数物”——应用层,表示层,会话层,传输层,网络层,数据链路层,物理层.而实际的Linux网络层协议是参照了OSI标准,但 ...

  4. 烂泥:通过binlog恢复mysql备份之前的数据

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 上一篇文章,我们讲解了如何通过mysql的binlog日志恢复mysql数据库,文章连接为<烂泥:通过binlog恢复mysql数据库>.其 ...

  5. x01.os.5: DOS 功能调用

    DOS 功能调用(INT 21)-------------------------------AH = 0-2E 适用 DOS 1.0 以上版本AH = 2F-57 适用 DOS 2.0 以上版本AH ...

  6. addrinfo 结构

    typedef struct addrinfo {int             ai_flags;int            ai_family;int             ai_sockty ...

  7. eclipse设置显示代码行数(转)

    (转自:http://jingyan.baidu.com/article/b2c186c89b7023c46ef6ff27.html) 载入eclipse的主页面,默认以英文版的eclipse为例 点 ...

  8. 深入理解TCP(二)

    上一篇http://www.cnblogs.com/whc-uestc/p/4715334.html中已经讲到TCP跟踪一个拥塞窗口来(cwnd)提供拥塞控制服务,通过调节cwnd值以控制发送速率.那 ...

  9. 理解 QEMU/KVM 和 Ceph(3):存储卷挂接和设备名称

    本系列文章会总结 QEMU/KVM 和 Ceph 之间的整合: (1)QEMU-KVM 和 Ceph RBD 的 缓存机制总结 (2)QEMU 的 RBD 块驱动(block driver) (3)存 ...

  10. Java Web之会话技术

    客户端与服务器通信过程中,会产生一些数据.比如,A和B分别登陆了某宝购物网站,A买了一个Android手机,B买了一个iPhone手机,当结账时,web服务器需要分别对用户A和B的信息分别保存.根据J ...