简体   繁体   English

等待多个AsyncTask完成

[英]Wait for multiple AsyncTask to complete

I am parallelizing my operation by splitting it in the exact number of cores available and then, by start the same number of AsyncTask, performing the same operation but on different portions of data. 我通过将其分成可用核心的确切数量来并行化我的操作,然后通过启动相同数量的AsyncTask,执行相同的操作但是在不同的数据部分上。

I am using executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ...) in order to parallelize the execution of them. 我正在使用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ...)来并行执行它们。

I would like to know when every thread finishes its job so that combine all results and perform further operations. 我想知道每个线程何时完成其工作,以便结合所有结果并执行进一步的操作。

How can I do? 我能怎么做?

You could also simply decrement a counter in a shared object as part of onPostExecute . 您还可以简单地减少共享对象中的计数器作为onPostExecute一部分。 As onPostExecute runs on the same thread (the main thread), you won't have to worry about synchronization. 由于onPostExecute在同一个线程(主线程)上运行,因此您不必担心同步。

UPDATE 1 更新1

The shared object could look something like this: 共享对象可能如下所示:

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

UPDATE 2 更新2

According to the comments for this answer, OP is looking for a solution in which he can avoid building a new class. 根据对这个答案的评论,OP正在寻找一种可以避免建立新课程的解决方案。 This can be done by sharing an AtomicInteger among the spawned AsyncTask s: 这可以通过在生成的AsyncTask共享AtomicInteger来完成:

// 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"));    
        }
    }
}

You should use a CountDownLatch. 您应该使用CountDownLatch。 Here the documentation with examples: java.util.concurrent.CountDownLatch 这里的文档包含示例: java.util.concurrent.CountDownLatch

Basically you give a reference of CountDownLatch to your threads, and each of them will decrement it when finished: 基本上你给你的线程提供了CountDownLatch的引用,并且它们中的每一个都会在完成时减少它:

countDownLatch.countDown();

The main thread will wait on the termination of all threads using: 主线程将使用以下命令等待所有线程的终止:

countDownLatch.await();

Another Option could be to store all your new threads in an Array. 另一个选项可能是将所有新线程存储在一个数组中。

Then you could iterate over the Array and wait with thread[i].join for the thread to finish. 然后你可以迭代数组并等待线程[i] .join完成线程。

see join() http://developer.android.com/reference/java/lang/Thread.html#Thread(java.lang.Runnable) 请参阅join() http://developer.android.com/reference/java/lang/Thread.html#Thread ( java.lang.Runnable)

When the Iteration is finished all your threads are done and you can work on 完成迭代后,所有线程都已完成,您可以继续操作

First, add this class to your project 首先,将此类添加到项目中

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

Then: 然后:

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

Then in each task - when completed, add the line: multiTaskHandler.taskComplete(); 然后在每个任务中 - 完成后,添加以下行: multiTaskHandler.taskComplete();

Example: 例:

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

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

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

You can use multiTaskHandler.cancel() if you want to cancel the code that runs when all the tasks have completed. 如果要取消在完成所有任务后运行的代码,可以使用multiTaskHandler.cancel() For instance - if you have an error (don't forget to also cancel all the other tasks). 例如 - 如果您有错误(不要忘记也取消所有其他任务)。

* This solution will not pause the main thread! *此解决方案不会暂停主线程!

RX Merge operator is your friend. RX Merge运营商是您的朋友。

Get rid of AsyncTark is slower than RX and you cannot handle Errors 摆脱AsyncTark比RX慢,你无法处理错误

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM