AsyncTask 只能执行一次

讨论两个问题:

第一个问题:一个AsyncTask对象只能被执行一次,即只能调用一次execute;

第二个问题:既然一个AsyncTask对象只能被执行一次,为什么AsyncTask还要用线程池;


第一个问题

刚开始用AsyncTask的时候就知道一个AsyncTask对象只能被执行一次,即只能调用一次execute;

其实对这个概念是模糊的,一直再用也就没有关注,今天晚上特地研究了一下到底是什么意思,也就是代码怎么实现才算是一次,怎么实现算是多次;

下面用代码说明:

第一种情况:同时直接都execute


通过按钮点击触发上面的方法,控制台得到的结果是:

第二种情况:先让myAsyncTask执行完任务,然后我再执行execute;


通过按钮点击触发上面的方法,任务执行为三秒,控制台得到的结果是:


上面两个例子就很显然了,一个AsyncTask对象只能执行一次,关键点就在“一个对象”上;

佐证

如果到这还不明那就看下这个例子,同样是MyAsyncTask对象,但是我new多次,每new一次就代表着一个新的对象,看代码:


同样看下点击按钮后控制台的信息:

到这这里就很清楚了,一个AsyncTask对象只能执行一次。

注:我一直纠结的问题就是一个AsyncTask只能执行一次,我恰恰是忽略“对象”两个字(这也就是我一直单着的原因吧,哈哈哈)。

下面是MyAsyncTask,这个文章中的MyAsyncTask都是同一个:


第二个问题

在同一进程下的所有AsyncTask的任务都会到达同一个任务对队列:

我们从 new MyAsyncTask("onlyonce 1").execute(); 说起,现在看下源码

    @MainThread
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

我们看到了executor调用的是executorOnExecutor在来看下它的源码

    @MainThread
    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {
        if (mStatus != Status.PENDING) {
            switch (mStatus) {
                case RUNNING:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task is already running.");
                case FINISHED:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task has already been executed "
                            + "(a task can be executed only once)");
            }
        }

        mStatus = Status.RUNNING;

        onPreExecute();

        mWorker.mParams = params;
        exec.execute(mFuture);

        return this;
    }

主要看exec.execute(mFuture)这一行。

exec是什么呢?从execute函数里面的实现就可以看到,exec是sDefaultExecutor,那么sDefaultExecutor是什么玩意呢?

从一下代码可以清楚的看到:

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

sDefaultExecutor是SerialExecutor的一个实例,而且它是个静态变量。也就是说,一个进程里面所有AsyncTask对象都共享同一个SerialExecutor对象。

    private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        Runnable mActive;

        public synchronized void execute(final Runnable r) {
            mTasks.offer(new Runnable() {
                public void run() {
                    try {
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });
            if (mActive == null) {
                scheduleNext();
            }
        }

        protected synchronized void scheduleNext() {
            if ((mActive = mTasks.poll()) != null) {
                THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }
    }
代码本身很简单,从execute里面就能看出,异步任务r被放到了ArrayDeque对象mTasks中,然后通过scheduleNext()来从mTasks里面得到一个任务去一个后台线程执行。

在一个异步任务执行后,再次调用scheduleNext来执行下一个任务(run函数)。
所以,很清楚,其实SerialExecutor是一个一个执行任务的,而所有的AsyncTask对象又共享同一个SerialExecutor对象(静态成员)。







  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在 Android 中,AsyncTask 是一种轻量级的异步任务处理方式,它可以在后台线程中执行任务,然后将结果返回到 UI 线程中进行处理。如果需要按照顺序同步执行多个任务,可以在 AsyncTask 中对任务进行排序并依次执行。 下面是一个按照顺序同步执行任务的 AsyncTask 示例代码: ```java public class MyTask extends AsyncTask<Void, Void, Void> { private List<Runnable> mTasks = new ArrayList<>(); public void addTask(Runnable task) { mTasks.add(task); } @Override protected Void doInBackground(Void... params) { for (Runnable task : mTasks) { task.run(); } return null; } } ``` 在上面的代码中,我们定义了一个 MyTask 类,它继承自 AsyncTask。我们使用一个 List 来存储所有需要执行的任务,并在 doInBackground() 方法中对任务进行排序并依次执行。我们还提供了一个 addTask() 方法,用于添加需要执行的任务。 我们可以这样使用 MyTask 类来执行多个任务: ```java MyTask task = new MyTask(); task.addTask(new Runnable() { @Override public void run() { // 执行任务1 } }); task.addTask(new Runnable() { @Override public void run() { // 执行任务2 } }); task.addTask(new Runnable() { @Override public void run() { // 执行任务3 } }); task.execute(); ``` 在上面的代码中,我们创建了一个 MyTask 对象,并依次添加了三个需要执行的任务。最后,我们调用 execute() 方法来启动异步任务。 需要注意的是,AsyncTask 并不保证任务的顺序执行,但是我们可以利用上述方式来实现顺序同步执行任务。同时,如果任务之间存在依赖关系,需要保证任务的执行顺序。可以使用线程或异步任务的等待机制来实现这种依赖关系。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值