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

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

分享到:
评论
发表评论

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

相关推荐

    Android-AsyncTask-Executor:已弃用 您想在任何版本的 Android 操作系统上同时执行您的 AsyncTask 吗? 你需要 AsyncTaskExecutor!

    AsyncTask-Executor 承担在任何 Android 操作系统版本上并发运行 AsyncTask 的所有工作,最好使用: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { task.executeOnExecutor(AsyncTask.THREAD_...

    AsyncTask类实例详解

    而在Android 9.0(API Level 28)之后,AsyncTask被弃用,推荐使用其他异步处理机制,如`Executor`服务。 综上所述,AsyncTask是Android中处理短时、轻量级异步任务的工具,它简化了多线程编程,并确保了UI线程的...

    Android AsyncTask 源码解析

    - **Executor**:AsyncTask 内部维护了一个 Executor 实例,用于调度任务的执行。默认的 SerialExecutor 使用一个串行队列,而 ParallelExecutor 则采用并发执行策略。 - **WorkerThread**:每个任务都在一个单独的...

    Android中使用ListView数据异步加载与AsyncTask

    开发者可以通过Adapter类将数据集与ListView绑定,Adapter负责将数据转换为子视图并插入ListView。 二、数据异步加载 1. 使用AsyncTask AsyncTask是Android提供的轻量级异步任务框架,用于在后台执行耗时操作,然后...

    AsyncTask异步任务三.rar

    在Android应用开发中,异步任务(AsyncTask)是一个非常重要的组件,主要用于处理那些需要在后台线程执行但又需要与UI交互的操作。AsyncTask使开发者能够轻松地在后台线程执行耗时操作,然后在主线程更新UI,避免了...

    AsyncTask小练习

    另外,从Android 3.0(API级别11)开始,AsyncTask的执行默认是在序列化的,意味着同一时间只能有一个AsyncTask实例在运行。如果需要并发执行多个任务,可以重写`executeOnExecutor()`方法指定`THREAD_POOL_EXECUTOR...

    AsyncTask使用实例

    - **生命周期管理**:AsyncTask与Activity的生命周期绑定,如果在Activity销毁时任务仍在运行,可能会导致内存泄漏。因此,需要在Activity的`onPause()`或`onDestroy()`中取消任务。 - **线程限制**:默认情况下,...

    AsyncTask的cancel的有效用法

    当我们需要取消一个正在运行的AsyncTask时,就需要理解并正确使用`cancel`方法。本文将深入探讨`AsyncTask`的`cancel`方法的有效用法以及如何实现强制停止`AsyncTask`异步任务。 ### 1. AsyncTask的基本结构 ...

    Android AsyncTask基础

    如果你需要并发执行多个任务,可以使用`executeOnExecutor()`方法并传入`AsyncTask.THREAD_POOL_EXECUTOR`。 理解并熟练使用AsyncTask对于开发Android应用至关重要,它可以帮助我们编写出更加流畅、用户体验更好的...

    AsyncTask下载网络图片 进度条提示

    请注意,Android从API 11开始推荐使用`Executor`和`IntentService`来替代`AsyncTask`,因为`AsyncTask`在多线程处理和内存管理上存在一些问题。但如果你的项目支持的最低API版本较低,`AsyncTask`仍然是一个可行的...

    AsyncTask应用下载MP3

    不过,需要注意的是,从Android 3.0(API Level 11)开始,`AsyncTask`的执行受到限制,可能不再在单独的线程中运行,因此在高版本系统上可能需要配合`Executor`使用,或者考虑使用其他的异步处理库,如`LiveData`、...

    AsyncTask 异步多线程加载Demo

    在Android开发中,AsyncTask是一种轻量级的异步任务处理机制,主要用于UI线程与后台线程之间的通信,以实现耗时操作的异步执行,避免阻塞主线程,提高用户体验。`AsyncTask`类提供了简单易用的接口,使得开发者能够...

    03_AsyncTask_异步方法操作之进度条

    在实际项目中,`AsyncTask`还可以与其他组件(如网络请求库)结合,实现更复杂的异步操作。然而,需要注意的是,由于`AsyncTask`的数量有限,并且在Android API 30及以上版本被废弃,对于大型项目或复杂逻辑,推荐...

    详解Android中用于线程处理的AsyncTask类的用法及

    AsyncTask 有四个主要的方法,每个方法都在特定的线程中运行: 1. **onPreExecute()**:在 UI 线程中运行,通常用于任务开始前的准备工作,如显示加载对话框。 2. **doInBackground(Params... params)**:在后台...

    Android AsyncTask的简单Demo

    然而,对于更复杂的任务或者需要长时间运行的后台服务,开发者应该选择其他更适合的机制,如IntentService或使用`Executor`配合`Handler`。理解`AsyncTask`的工作原理和生命周期管理是编写高效、健壮的Android应用的...

    简介Android 中的AsyncTask

    当一个Activity被销毁时,它的AsyncTask并不会自动取消,而是继续在后台运行。这可能导致内存泄漏或意外的行为,因为即使Activity已经不存在,AsyncTask仍然可能会尝试更新已销毁的UI。为了避免这种情况,开发者需要...

    Android asyncTask的使用

    值得注意的是,`AsyncTask`的生命周期与Activity是绑定的,如果在Activity中创建了一个`AsyncTask`实例并在Activity销毁前没有结束,那么当Activity被销毁后,`AsyncTask`可能会继续执行,导致内存泄漏。因此,推荐...

    AsyncTask异步加载使用

    如果需要顺序执行,可以重写`executeOnExecutor()`方法,传入 SERIAL_EXECUTOR 参数。 通过这个Demo,你应该对AsyncTask有了初步的理解。然而,随着Android版本的更新,对于长时间运行的任务,推荐使用其他更高级的...

    模范Android中的AsyncTask

    - `AsyncTask`不适合长时间运行的任务,因为它可能被系统回收,特别是在配置更改(如屏幕旋转)时。 4. **与Looper和Handler的关系** - 在Android中,`Looper`和`Handler`是用于在主线程中处理消息和执行回调的...

    AsyncTask实例

    - Android 3.0及以上版本,AsyncTask默认使用序列化执行,即一次只有一个任务运行。可以通过设置`AsyncTask.THREAD_POOL_EXECUTOR`来改变这一行为。 4. **取消任务** 可以通过调用`cancel(boolean ...

Global site tag (gtag.js) - Google Analytics