异步任务 AsynTask 创建之后可以通过 execute()方法执行多次么?

不能,只能执行一次。为什么?

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

当我们调用execute()来执行任务时,其实是调用如下方法。

public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) 

下面贴出一些代码:

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;  
}  

从注释中,我们就可以知道,一个任务不能被执行多次,当该任务的状态是 Running、Finished时,会抛出异常。

那么为什么要抛出异常呢?
这里写图片描述

我们可以看到,当我们使用异步任务中维护的线程池进行任务的执行时,其实是执行了一个FutureTask,而FutureTask是封装了一个Callable的。

当我们调用线程池执行任务时,会从任务队列中取得FutureTask任务,取出任务之后调用FutureTask.run()方法,而在FutureTask.run()方法中则会调用Callable.call()方法来真正的执行这一个Callable任务,并且是可以回调将运行结果获取到的。获取到的运行结果就是doInBackground()方法的返回值。

在我们执行一个FutureTask时,我们可以看到下面的代码,是FutureTask的run方法,在run方法执行时,会判断callable任务是否为空,如果为空,调用setException(ex)返回一个异常,如果不为空,则执行,并在result返回结果,然后将状态设置为 ran。最后调用 set(result)设置运行的结果就是callable的结果。

重点:

在setException(ex)、set(result)中都调用了一个方法,finishCompletion()。最后再这个方法中将callable置为了null。
一切都清楚了,在线程池分配线程来执行任务FutureTask时,会调用它的run方法来启动它,在run方法内部,会调用FutureTask的真正任务实体Callable的call方法。最后执行完之后,如果callable为null,抛出异常,如果不为null,执行完之后,置为null。
因此,一个任务只能执行一次。

public void run() {  
    if (state != NEW ||  
        !UNSAFE.compareAndSwapObject(this, runnerOffset,  
                                     null, Thread.currentThread()))  
        return;  
    try {  
        Callable<V> c = callable;  
        if (c != null && state == NEW) {  
            V result;  
            boolean ran;  
            try {  
                result = c.call();  
                ran = true;  
            } catch (Throwable ex) {  
                result = null;  
                ran = false;  
                setException(ex);  
            }  
            if (ran)  
                set(result);  
        }  
    } finally {  
        // runner must be non-null until state is settled to  
        // prevent concurrent calls to run()  
        runner = null;  
        // state must be re-read after nulling runner to prevent  
        // leaked interrupts  
        int s = state;  
        if (s >= INTERRUPTING)  
            handlePossibleCancellationInterrupt(s);  
    }  
}  
private void finishCompletion() {  
    // assert state > COMPLETING;  
    for (WaitNode q; (q = waiters) != null;) {  
        if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {  
            for (;;) {  
                Thread t = q.thread;  
                if (t != null) {  
                    q.thread = null;  
                    LockSupport.unpark(t);  
                }  
                WaitNode next = q.next;  
                if (next == null)  
                    break;  
                q.next = null; // unlink to help gc  
                q = next;  
            }  
            break;  
        }  
    }  

    done();  

    callable = null;        // to reduce footprint  
}  

猜你喜欢

转载自blog.csdn.net/scuzoutao/article/details/77844091
今日推荐