AsyncTask的运行与Executor androidAsyncTaskExecutor
帮同事看一个问题: 工程下面同时触发两个的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.) 如果你的线程需要执行一段较长的时间的话, 还是另谋生路吧(这个生路怎么谋, 文档里也有写, 这里就不列上来了).
推荐阅读
-
【求指导】自学与新浪微博开放平台对接,运行新浪提供的SDK报错
-
PHP的运行机制与原理(底层)_PHP
-
MySQL 联合索引与Where子句的优化 提高数据库运行效率
-
java异常继承何类,运行时异常与一般异常的区别(详解)
-
MySQL 联合索引与Where子句的优化 提高数据库运行效率
-
AsyncTask陷阱之:Handler,Looper与MessageQueue的详解
-
AsyncTask陷阱之:Handler,Looper与MessageQueue的详解
-
PHP运行环境配置与开发环境的配置(图文教程)
-
Java : 多态表现:静态绑定与动态绑定(向上转型的运行机制)
-
Python获取运行目录与当前脚本目录的方法