`
OliveExcel
  • 浏览: 70458 次
文章分类
社区版块
存档分类
最新评论

AsyncTask的运行与Executor

阅读更多

帮同事看一个问题: 工程下面同时触发两个的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.) 如果你的线程需要执行一段较长的时间的话, 还是另谋生路吧(这个生路怎么谋, 文档里也有写, 这里就不列上来了).

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

Global site tag (gtag.js) - Google Analytics