资讯专栏INFORMATION COLUMN

串行还是并行?——记一次 AsyncTask 问题排查

mo0n1andin / 3407人阅读

摘要:当然,如果你的核心数够多,到个线程的并行度不满足的话,也可以自定义一个线程池来执行,不过这样的话,要注意自己维护这个线程池的初始化,释放等等操作了。

事情起源于一个bug排查,一个AsyncTask的子类,执行的时候发现onPreExecute方法执行了,doInBackground却迟迟没有被调用。
懂AsyncTask一些表面原理的都知道,onPreExecute方法是在主线程执行,doInBackground方法是在后台线程执行,所以很明显是后台线程被卡住了执行不了,所以这就涉及到AsyncTask的原理问题了,查看出现bug的版本——Android 6.0源码可以知道,AsyncTask里面维护着两个线程池,THREAD_POOL_EXECUTOR和SERIAL_EXECUTOR,其中SERIAL_EXECUTOR是默认的线程池:

如果用AsyncTask.execute(params...)方法来执行任务,就会用到默认的线程池,即SERIAL_EXECUTOR;可以看出SERIAL_EXECUTOR会让所有的线程串行执行:

而且由于SERIAL_EXECUTOR被声明为static,所以,同一个进程里的AsyncTask都会共享这个线程池,这就意味着,在同一个进程里,前面的线程不结束,后面的线程就会被挂起,这正是我遇到的情况。
接下来排查所有用AsyncTask.execute方法来执行任务的情况,终于找到了一个不合理的调用————在doInBackground里请求网络,一直死等response,而没有超时释放。修复了这种情况,问题就迎刃而解了。

除了这种解决前面线程不合理设计的办法,还有没有别的解决方式呢,因为有时候,我们的设计确实是让后台线程死循环,不跳出的。

当然有的,在AsyncTask设计上就考虑到了,前面说到AsyncTask里面还有一个线程池THREAD_POOL_EXECUTOR,从它的初始化参数可以看出,这是一个支持2到4个线程并行的线程池:

所以,使用AsyncTask执行任务的时候,请使用AsyncTask.executeOnExecutor(THREAD_POOL_EXECUTOR)来让你的任务跑在并行的线程池上,避免出现并前面线程阻塞的情况。当然,如果你的CPU核心数够多,2到4个线程的并行度不满足的话,也可以自定义一个线程池来执行AsyncTask,不过这样的话,要注意自己维护这个线程池的初始化,释放等等操作了。

PS:AsyncTask是不是一开始就是被设计成这样的呢?笔者调研了一下,其实Android 1.5刚开始引入AsyncTask的时候,execute方法确实是串行执行的,类定义里面只有SERIAL_EXECUTOR线程池;到1.6版本时,改用并行线程池THREAD_POOL_EXECUTOR,再到3.0版本至今,就成了上面说的模样————定义两个线程池,但是默认用串行池。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/67602.html

相关文章

  • 串行还是并行?——一次 AsyncTask 问题排查

    摘要:当然,如果你的核心数够多,到个线程的并行度不满足的话,也可以自定义一个线程池来执行,不过这样的话,要注意自己维护这个线程池的初始化,释放等等操作了。 事情起源于一个bug排查,一个AsyncTask的子类,执行的时候发现onPreExecute方法执行了,doInBackground却迟迟没有被调用。懂AsyncTask一些表面原理的都知道,onPreExecute方法是在主线程执行,...

    ivyzhang 评论0 收藏0
  • AsyncTask异步任务类

    摘要:异步任务的构造方法主要用于初始化线程池先关的成员变量创建一个新的异步任务。所以,我们是必须确保在销毁活动之前取消任务。 目录介绍 01.先看下AsyncTask用法 02.AsyncTask源码深入分析 2.1 构造方法源码分析 2.2 看execute(Params... params)方法 2.3 mWorker和mFuture的创建过程 03.异步机制的实现 04.不同...

    dongxiawu 评论0 收藏0
  • 一次Node项目的优化

    摘要:相关环境由于是一个几年前的项目,所以使用的是这样的。一些小提示本次优化笔记,并不会有什么文件的展示。将异步改为了串行,丧失了作为异步事件流的优势。 这两天针对一个Node项目进行了一波代码层面的优化,从响应时间上看,是一次很显著的提升。 一个纯粹给客户端提供接口的服务,没有涉及到页面渲染相关。 背景 首先这个项目是一个几年前的项目了,期间一直在新增需求,导致代码逻辑变得也比较复杂,接...

    dreamans 评论0 收藏0
  • Android的线程和线程池

    摘要:主线程和子线程沿用了的线程模型,其中的线程也分为主线程和子线程,其中主线程也叫线程。主线程的作用是运行四大组件以及处理它们和用户的交互,而子线程的作用则是执行耗时任务,比如网络请求操作等。 前言 线程在Android中是一个很重要的概念,从用途上来说,线程分为主线程和子线程,主线程主要处理和界面相关的事情,而子线程则往往用于执行耗时操作。由于Android的特性,如果在主线程中执行耗时...

    yck 评论0 收藏0
  • 一次 MySQL 数据库问题排查

    摘要:完成此次修改后,这个异常没有再复现,但是响应缓慢的情况依然没有得到缓解。问题一条引发的血案我们再次查看了错误日志,发现了另一个异常报错。不可重复读事务还没有结束时,事务也访问同一数据。 最近遇到应用频繁的响应缓慢,无法正常访问。帮忙一起定位原因,最后定位到的问题说起来真的是很小的细节问题,但是就是这些小细节导致了服务不稳定,真是细节决定成败。这里尝试着来分享下,希望对大家有所帮助。 问...

    marser 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<