Moosphan/Android-Daily-Interview

2019-04-15:AsyncTask的优点和缺点?

FeatherHunter opened this issue · 9 comments

2019-04-15:AsyncTask的优点和缺点?

优点:使用方便,然后没了
缺点:在各版本系统差异极大,比如1.6时只能串行执行,2.1时改成并行执行,3.0默认又改成了串行,想要并行执行需要使用默认的线程池;5.1以下AsyncTask只能在主线程开启,4.x(具体版本记不清了)以下初始化(指执行时)也必须在主线程;官方文档上说onPreExecute方法是在主线程中执行的,但是查看源码发现竟然是在execute()里就执行了;
所以自定义一个比较好

优点:AsyncTask操作简单,轻便,适用简单的异步操作。
缺点:存在新开大量线程,消耗系统资源的风险

优点:使用方便,既可以执行串行任务,也可以执行并行任务
缺点:默认使用串行任务执行效率低,不能充分利用多线程加快执行速度;如果使用并行任务执行,在任务特别多的时候会阻塞UI线程获得CPU时间片,后续做线程收敛需要自定义AsynTask,将其设置为全局统一的线程池,改动量比较大

有点:方便
缺点:不可控制

AsyncTask的实现原理:
1.AsyncTask是一个抽象类,主要由Handler+2个线程池构成,SERIAL_EXECUTOR是任务队列线程池,用于调度任务,按顺序排列执行,THREAD_POOL_EXECUTOR是执行线程池,真正执行具体的线程任务。Handler用于工作线程和主线程的异步通信。

2.AsyncTask<Params,Progress,Result>,其中Params是doInBackground()方法的参数类型,Result是doInBackground()方法的返回值类型,Progress是onProgressUpdate()方法的参数类型。

3.当执行execute()方法的时候,其实就是调用SERIAL_EXECUTOR的execute()方法,就是把任务添加到队列的尾部,然后从头开始取出队列中的任务,调用THREAD_POOL_EXECUTOR的execute()方法依次执行,当队列中没有任务时就停止。

4.AsyncTask只能执行一次execute(params)方法,否则会报错。但是SERIAL_EXECUTOR和THREAD_POOL_EXECUTOR线程池都是静态的,所以可以形成队列。

Q:AsyncTask只能执行一次execute()方法,那么为什么用线程池队列管理 ?
因为SERIAL_EXECUTOR和THREAD_POOL_EXECUTOR线程池都是静态的,所有的AsyncTask实例都共享这2个线程池,因此形成了队列。

Q:AsyncTask的onPreExecute()、doInBackground()、onPostExecute()方法的调用流程?
AsyncTask在创建对象的时候,会在构造函数中创建mWorker(workerRunnable)和mFuture(FutureTask)对象。
mWorker实现了Callable接口的call()方法,在call()方法中,调用了doInBackground()方法,并在最后调用了postResult()方法,也就是通过Handler发送消息给主线程,在主线程中调用AsyncTask的finish()方法,决定是调用onCancelled()还是onPostExecute().
mFuture实现了Runnable和Future接口,在创建对象时,初始化成员变量mWorker,在run()方法中,调用mWorker的call()方法。
当asyncTask执行execute()方法的时候,会先调用onPreExecute()方法,然后调用SERIAL_EXECUTOR的execute(mFuture),把任务加入到队列的尾部等待执行。执行的时候调用THREAD_POOL_EXECUTOR的execute(mFuture).

所有的asyctask 共享 两个线程池 一个用来排队 一个用来执行任务
asyctask中的任务默认是串行的,但是可以通过配置实现 并行
默认串行导致一个问题 asyctask只能用来处理 短暂的任务 非常耗时的任务请使用线程池,否则会过长等待

优点:
方便实现异步操作和UI的更新
不需要能过handle和线程组合进行异步操作和UI更新
缺点
不同的多耗时操作时 要创建不同的AsyncTask这样搞得很乱很复杂 复用性不是那么高

补充一个链接,我觉得说得不错的:http://www.voycn.com/article/asynctaskdequexianhezhuyishixiang

Deprecated
Use the standard java.util.concurrent or Kotlin concurrency utilities instead.