帮同事看一个问题: 工程下面同时触发两个的AsyncTask, 预期可以同时执行, 但实际结果它们是顺序执行的.
思不得解, 百度一把, 看到有人问怎样控制多AsyncTask的运行优先级, 然后有人回复了一行代码:
AsyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, null);
虽然代码完全没有解决问题, 但是看得出, 这里有一些并发设计相关的东西AsyncTask.SERIAL_EXECUTOR. 它是一个顺序Executor, 并且一次只能执行一个线程. 代码中定义如下:
/** * An {@link Executor} that executes tasks one at a time in serial * order. This serialization is global to a particular process. */ public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
上述SerialExecutor关键代码:
public synchronized void execute(final Runnable r) { ... try { r.run(); } finally { scheduleNext(); } ... }
那么, 多个AsyncTask同时执行变成顺序执行, 是否也是受Executor的约束呢?
我们来看一下AsyncTask.execute(Parmas): 里面简简单单就一行:
return executeOnExecutor(sDefaultExecutor, params);
于是明白execute其实也是通过executeOnExecutor()实现的, 只是指定了默认的Executor. 再来看sDefaultExecutor:
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
这又回到了上面提到的顺序Executor.
到这里, 同事碰到问题的原因就找到了:
1. 虽然构造了多个AsyncTask实例, 并且都通过execute()执行起来
2. 但由于它们共享了同一个sDefaultExecutor(它是以static修饰的);
3. sDefaultExecutor同一时间只执行一个线程;
4. 因此这些AsyncTask实例同时启动后是顺序执行的..
================================ 继续读代码的分割线 ================================
在看代码过程中, 注意到几个地方:
1. sDefaultExecutor它是个类静态成员:
从而整个系统中整个进程中, 所有通过execute()启动的AsyncTask, 都是在顺序执行. 那么如果你的AsyncTask在execute后许久仍不执行, 很可能就是被其他task block住了.
2. sDefaultExecutor它不是final的:
存在这样的可能性, 重新赋值sDefaultExecutor, 使之可同时执行多个线程. 相应的, 可以找到一个标记为@hide的方法: setDefaultExecutor(Executor exec). 如果通过反射直接操作sDefaultExecutor, 或者调用setDefaultExecutor(), 均可以改变AsyncTask的顺序执行逻辑. 但需要注意到, 这个逻辑改变会影响到系统中所有用到AsyncTask的地方.
3. Android官方文档:
AsyncTask的文档中有这样的描述: AsyncTasks should ideally be used for short operations (a few seconds at the most.) 如果你的线程需要执行一段较长的时间的话, 还是另谋生路吧(这个生路怎么谋, 文档里也有写, 这里就不列上来了).
相关推荐
AsyncTask.java,AsyncTask.java,AsyncTask.java,AsyncTask.java
AsyncTask-Executor 承担在任何 Android 操作系统版本上并发运行 AsyncTask 的所有工作,最好使用: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { task.executeOnExecutor(AsyncTask.THREAD_...
自己写了一个基于httpurlconnection和Asynctask的例子
AsyncTask与Handler实现进度条的方式
Handler与AsyncTask使用示例,Handler AsyncTask 示例 looper
AsyncTask的用法
AsyncTask_简单演示AsyncTask异步操作,写一个简单的AsyncTask异步操作解决上一篇文章提到的线程阻塞问题,对应我的博客《网易博客迁移:Android专题之AsyncTask(二)简单演示AsyncTask异步操作》,有问题欢迎留言...
三种不同的方式讲述了如何开辟新线程处理进度条的更新。运行时需修改Mainfest,来用不同的方式运行。默认是使用AsyncTask运行
异步任务Asynctask源码与反编译对比,来分析源代码
Android AsyncTask异步处理下载网页
doInBackground(Params...), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法...
最新AsyncTask源码
Android中使用ListView数据异步加载与AsyncTask,获取网络资源,线程池技术,多线程技术。
比较了handler加thread 和 AsyncTask 在处理消息的不同,详见博客 http://blog.csdn.net/renlei0109/article/details/39524463
AsyncTask 断点下载
Android AsyncTask的简单Demo,对应Blog文章:http://blog.csdn.net/dolacmeng/article/details/50215519
android 任务后台处理事物 asyncTask封装
Android Handler AsyncTask 异步加载
一个ListView的小例子,一开始List中没有内容,通过一个AsyncTask逐步在List中加入条目,适合新手学习AsyncTask多线程,本人整理能运行,有详细的注解。
Android AsyncTask用法和异步加载图片通过AsyncTask 从网络上异步加载一张图片