java 等待多个 AsyncTask 完成
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32625599/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Wait for multiple AsyncTask to complete
提问by Nicholas Allio
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?
我能怎么做?
采纳答案by Janus Varmarken
You could also simply decrement a counter in a shared object as part of onPostExecute
. As onPostExecute
runs on the same thread (the main thread), you won't have to worry about synchronization.
您也可以简单地减少共享对象中的计数器作为onPostExecute
. 由于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. This can be done by sharing an AtomicInteger
among the spawned AsyncTask
s:
根据对此答案的评论,OP 正在寻找一种解决方案,在该解决方案中他可以避免构建新类。这可以通过AtomicInteger
在生成的AsyncTask
s之间共享一个来完成:
// 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"));
}
}
}
回答by Pouriya Zarbafian
You should use a CountDownLatch. Here the documentation with examples: java.util.concurrent.CountDownLatch
您应该使用 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();
回答by Gil SH
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. For instance - if you have an error (don't forget to also cancel all the other tasks).
multiTaskHandler.cancel()
如果要取消所有任务完成后运行的代码,可以使用。例如 - 如果您有错误(不要忘记同时取消所有其他任务)。
* This solution will not pause the main thread!
* 此解决方案不会暂停主线程!
回答by Duna
回答by Andriel
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.
然后你可以遍历数组并使用 thread[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
当迭代完成时,你的所有线程都完成了,你可以继续工作