深入浅出AsyncTask的工作原理

本文深入探讨了Android中AsyncTask的工作原理,包括其使用的数据结构如Executor、BlockingQueue等,并详细解释了源码中的关键部分。尽管现代开发中有其他异步处理方式,如RxJava,但理解AsyncTask的实现对于开发者仍有价值。文中还通过测试程序展示了AsyncTask的串行和并行执行模式,并提醒读者注意其执行限制和线程池的配置。
摘要由CSDN通过智能技术生成

前言

AsyncTask类一般是android开发人员接触的最早的异步处理方法,虽然现在流行的有很多新的异步任务类,如RxJava等,但是对于AsyncTask的底层实现原理还是有必要了解学习的,对于我们自己理解其他框架或者自己设计框架都有很大的帮助。它使用handler和线程池的方式打到异步操作,将结果返回到主线程处理。

数据结构

在讲解AsyncTask的原理前,我们需要先来复习或者学习下其用到的数据结构。这些是我们必须要了解的数据结构。

An object that executes submitted Runnable tasks. This interface provides a way of decoupling task submission from the mechanics of how each task will be run, including details of thread use, scheduling, etc. An Executor is normally used instead of explicitly creating threads. For example, rather than invoking new Thread(new(RunnableTask())).start() for each of a set of tasks, you might use:
//这是一个执行提交的Runnable类型的任务的接口,
//该接口提供了一种将任务提交与如何运行每个任务的机制分离的方法,
//包括线程使用、调度细节等。通常使用执行程序而不是显式地创建线程。
//即不需要为每个任务创建线程。
 Executor executor = anExecutor;
 executor.execute(new RunnableTask1());
 executor.execute(new RunnableTask2());
 //许多Executor实现对如何以及何时调度任务施加了某种限制。
 //即扩展类可以添加自己的调度方案,如顺序执行或者线程池并行执行。
 Many Executor implementations impose some sort of limitation on how and when tasks are scheduled. The executor below serializes the submission of tasks to a second executor, illustrating a composite executor. 
  • BlockingQueue
    阻塞队列,包名java.util.concurrent.BlockingQueue,和Excutor一样都是java jdk中并发相关的类。其大意是一个装载了Runnable任务的阻塞队列,阻塞队列即如果队列满,再次插入任务会阻塞住,直到有数据被取走。反之,如果队列空,再取任务时也会阻塞,直到有新任务插入。 当然这个BlockingQueue为泛型,<>其数据为插入的任何类型。在本例中是Runnable。如果还需要深入了解其原理请移步我的另一篇博客:BlockingQueue阻塞队列原理解析,还对其他实现类有描述。

  • AtomicInteger FutureTask
    java的JDK类中的原子类型的Integer,完整路径java.util.concurrent.atomic.AtomicInteger, atomic包代表的是原子类,其提供了incrementAndGet等函数,保证对象以原子方式进行改变。
    非原子性的解释, 比如变量 int a = 0;然后,
    a++; 这个a++其实就不是原子操作,比如其经过了获取值、值+1、赋值等三个操作(大概是,有待确认),如果在多线程中就会发生被其他线程更改的问题。

  • ArrayDeque Callable
    双端队列,区别于普通队列的FIFO特性,即先进先出,尾部进,头部出。双端队列是可以既在头部插入、尾部插入、头部取出、尾部取出的数据结构。

  • WorkerRunnable extends Callable
    本文的实现类是WorkerRunnable , Callable是同Runnable类似的数据结构。其中Runnable是一个没有参数和返回值的异步方法。那Callable那,既然是两个数据结构,这个肯定有不同,那就是其有返回值,而且是一个参数化的泛型类型,可以将要返回的数据类型传入,这里是Result。Runnable有一个run方法, Callable只有一个Call方法。

 public interface Callable<V>{
   
 	V call() throws Exception;
 }
  • FutureTask
    Future保存异步计算的结果,可以启动一个任务,将Future对象交给某个线程。Future对象的所有者在结果计算好之后就可以获得它。

从其类注释可以看出 其继承了Runnable,即可以提交到Executor中执行,并且其泛型结构体中可以传入Callable参数, 其还提供了get方法,以获取返回值,get方法会阻塞,知道执行成功。

A cancellable asynchronous computation. This class provides a base implementation of Future, with methods to start and cancel a computation, query to see if the computation is complete, and retrieve the result of the computation. The result can only be retrieved when the computation has completed; **the get methods will block if the computation has not yet completed**. 
//其get方法可能被阻塞,如果计算还未完成的话。

//FutureTask可以包装一个Callable或者Runnable类型。
A FutureTask can be used to wrap a Callable or Runnable object. Because FutureTask implements Runnable, a FutureTask can be submitted to an Executor for execution.

 public class FutureTask<V>
extends Object
implements RunnableFuture<V>

FutureTask(Callable<V> callable)
Creates a FutureTask that will, upon running, execute the given Callable.

 	get()
Waits if necessary for the computation to complete, and then retrieves its result.
  • InternalHandler extends Handler
    这个就相当简单了,Handler肯定大家都用过,这里是拿到了主线程的Looper的Handler将结果发送主线程使用。如果需要深入了解,请查阅我的另一篇博文:Handler通信机制源码解读

源码解读

通过上面的数据结构解读,其实基本上源码就清晰了。
由于AsyncTask是一个抽象类,所以使用时需要实现这个类,并实现抽象方法doInBackground, 其他的三个方法可以根据需要选择是否重新实现。其中
doInBackground是在线程池中执行的,其他三个都是在主线程执行的。

public abstract class AsyncTask<Params, Progress, Result> {
   
    @WorkerThread
    protected abstract Result doInBackground(Params... params);
    
    @MainThread
    protected void onPreExecute
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值