等待多个AsyncTask完成

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了等待多个AsyncTask完成相关的知识,希望对你有一定的参考价值。

我通过将其分成可用核心的确切数量来并行化我的操作,然后通过启动相同数量的AsyncTask,执行相同的操作但是在不同的数据部分上。

我正在使用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ...)来并行执行它们。

我想知道每个线程何时完成其工作,以便结合所有结果并执行进一步的操作。

我能怎么做?

答案

你也可以简单地减少共享对象中的计数器作为onPostExecute的一部分。由于onPostExecute在同一个线程(主线程)上运行,因此您不必担心同步。

更新1

共享对象可能如下所示:

public class WorkCounter {
    private int runningTasks;
    private final Context ctx;

    public WorkCounter(int numberOfTasks, Context ctx) {
        this.runningTasks = numberOfTasks;
        this.ctx = ctx;
    }
    // Only call this in onPostExecute! (or add synchronized to method declaration)
    public void taskFinished() {
        if (--runningTasks == 0) {
            LocalBroadcastManager mgr = LocalBroadcastManager.getInstance(this.ctx);
            mgr.sendBroadcast(new Intent("all_tasks_have_finished"));
        }
    }
}

更新2

根据对这个答案的评论,OP正在寻找一种可以避免建立新课程的解决方案。这可以通过在产生的AtomicIntegers中共享AsyncTask来完成:

// TODO Update type params according to your needs.
public class MyAsyncTask extends AsyncTask<Void,Void,Void> {
    // This instance should be created before creating your async tasks.
    // Its start count should be equal to the number of async tasks that you will spawn.
    // It is important that the same AtomicInteger is supplied to all the spawned async tasks such that they share the same work counter.
    private final AtomicInteger workCounter;

    public MyAsyncTask(AtomicInteger workCounter) {
        this.workCounter = workCounter;
    }

    // TODO implement doInBackground

    @Override
    public void onPostExecute(Void result) {
        // Job is done, decrement the work counter.
        int tasksLeft = this.workCounter.decrementAndGet();
        // If the count has reached zero, all async tasks have finished.
        if (tasksLeft == 0) {
            // Make activity aware by sending a broadcast.
            LocalBroadcastManager mgr = LocalBroadcastManager.getInstance(this.ctx);
            mgr.sendBroadcast(new Intent("all_tasks_have_finished"));    
        }
    }
}
另一答案

您应该使用CountDownLatch。这里的文档包含示例:java.util.concurrent.CountDownLatch

基本上你给你的线程提供了CountDownLatch的引用,并且它们中的每一个都会在完成时减少它:

countDownLatch.countDown();

主线程将使用以下命令等待所有线程的终止:

countDownLatch.await();
另一答案

另一个选项可能是将所有新线程存储在一个数组中。

然后你可以迭代数组并等待线程[i] .join完成线程。

看加入()http://developer.android.com/reference/java/lang/Thread.html#Thread(java.lang.Runnable)

完成迭代后,所有线程都已完成,您可以继续操作

另一答案

首先,将此类添加到项目中

public abstract class MultiTaskHandler {
    private int mTasksLeft;
    private boolean mIsCanceled = false;

    public MultiTaskHandler(int numOfTasks) {
        mTasksLeft = numOfTasks;
    }

    protected abstract void onAllTasksCompleted();

    public void taskComplete()  {
        mTasksLeft--;
        if (mTasksLeft==0 && !mIsCanceled) {
            onAllTasksCompleted();
        }
    }

    public void reset(int numOfTasks) {
        mTasksLeft = numOfTasks;
        mIsCanceled=false;
    }

    public void cancel() {
        mIsCanceled = true;
    }
}

然后:

int totalNumOfTasks = 2; //change this to the number of tasks that you are running
final MultiTaskHandler multiTaskHandler = new MultiTaskHandler(totalNumOfTasks) {
    @Override
    protected void onAllTasksCompleted() {
       //put the code that runs when all the tasks are complete here
    }
};

然后在每个任务中 - 完成后,添加以下行:multiTaskHandler.taskComplete();

例:

(new AsyncTask<Void,Void,Void>() {

    @Override
    protected Void doInBackground(Void... voids) {
        // do something...
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        multiTaskHandler.taskComplete();
    }
}).execute();

如果要取消所有任务完成时运行的代码,可以使用multiTaskHandler.cancel()。例如 - 如果您有错误(不要忘记也取消所有其他任务)。

*此解决方案不会暂停主线程!

以上是关于等待多个AsyncTask完成的主要内容,如果未能解决你的问题,请参考以下文章

等待 AsyncTask 完成,然后在 Android Java 中执行下一个代码

片段中的 Asynctask 未到达 onPostExecute

等待 Google 在 AsyncTask 中放置照片请求

让一个 AsyncTask 等待另一个完成?

Android AsyncTask 等待其他函数完成

在返回结果之前等待 AsyncTask.execute(()) 完成