在Java线程中,您可以在列表中包含一些线程,启动它们,然后使用主线程join
,然后执行另一个线程,等待所有进程完成后再继续。
在其他型号中,我不确定你会怎么做。以RootTools 3.0 Command类为例。您创建的Command
有三种方法,commandOutput
,commandFinished
,commandTerminated
,虽然您可以使用回调在流程结束时执行某些操作,但我不会我不知道你将如何等待多个进程(例如,浏览几个目录的列表并总结文件大小)。
我相信Android Asynctask会有类似的问题 - 你可以很容易地进行回调,但是没有办法等待几个任务。除非我错过了什么?
答案 0 :(得分:2)
您可以对正在执行的命令调用wait()。
虽然在执行此操作之前,您应该关闭您调用wait的命令的处理程序。您可以通过将RootTools.handlerEnabled设置为false或在每个单独的命令中使用构造函数并传入false来禁用该命令的处理程序来为每个命令执行此操作。
这很重要,因为如果使用了处理程序,那么它将尝试在你调用wait()的线程上调用回调方法,这将导致死锁。
当你为命令关闭处理程序并调用wait()时,命令会在完成后调用notifyAll(),这样你的线程就会恢复。
这方面的负面影响是,回调方法将不再在您正在处理的线程中完成,因此除非您实现处理程序或其他可接受的处理程序,否则您将无法使用这些回调方法执行任何UI工作处理这个的解决方案。
答案 1 :(得分:0)
使用CountDownLatch,我会在这里复制他们的用法示例以获得更好的语法突出显示(:
class Driver { // ...
void main() throws InterruptedException {
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(N);
for (int i = 0; i < N; ++i) // create and start threads
new Thread(new Worker(startSignal, doneSignal)).start();
doSomethingElse(); // don't let run yet
startSignal.countDown(); // let all threads proceed
doSomethingElse();
doneSignal.await(); // wait for all to finish
}
}
class Worker implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
this.startSignal = startSignal;
this.doneSignal = doneSignal;
}
public void run() {
try {
startSignal.await();
doWork();
doneSignal.countDown();
} catch (InterruptedException ex) {} // return;
}
void doWork() { ... }
}
答案 2 :(得分:0)
我在上一个项目中浏览了该主题,并找到了解决该问题的不同方法(我最终在项目中使用了方法1,因为它最适合该方法)。我将与您尽可能简单地分享它们。为了更好地理解,我将以下载多个图像的示例为例进行解释。
让ImageDownloader
成为从URL异步下载图像的类,它具有以下属性。
ImageDownloadCallback
,用于在任务完成时获取回调。它有两种方法
void onSuccess(String imagePath)
:任务成功完成时调用。void onFailure()
:在任务未能完成时调用。download(String url, ImageDownloadCallback callback)
启动下载任务 PauseModeCallbackHandler
,ChainModeCallbackHandler
和ParallelModeCallbackHandler
分别是这三种方法的回调的包装器类。您可以根据要执行的任务对其进行自定义。
通过暂停启动线程一个接一个地执行任务。
专业人士
在原始线程中获取结果
缺点
需要让线程等待
您可以使用此类使线程等待直到获得结果。
import java.util.concurrent.atomic.AtomicReference;
/**
* @author Ahamad Anees P.A
* @version 1.0
* @param <T> type
*/
public class ThreadLockedTask<T> {
private AtomicReference<ResultWrapper<T>> mReference;
public ThreadLockedTask() {
mReference = new AtomicReference<>(new ResultWrapper<T>());
}
public T execute(Runnable runnable) {
runnable.run();
if (!mReference.get().mIsSet)
lockUntilSet();
return mReference.get().mResult;
}
private void lockUntilSet() {
synchronized (this) {
while (!mReference.get().isSet()) {
try {
wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public void setResult(T result) {
synchronized (this) {
ResultWrapper<T> wrapper = mReference.get();
wrapper.setResult(result);
wrapper.setIsSet(true);
notify();
}
}
public static class ResultWrapper<T> {
private boolean mIsSet;
private T mResult;
public boolean isSet() {
return mIsSet;
}
public T getResult() {
return mResult;
}
void setIsSet(boolean isCompleted) {
this.mIsSet = isCompleted;
}
void setResult(T result) {
this.mResult = result;
}
}
}
import java.util.ArrayList;
import java.util.List;
public class PauseModeCallbackHandler {
// List of results
private static List<String> results;
public static void start(final List<String> urls, final ImageDownloader.ProgressUpdateListener listener) {
new Thread(new Runnable() {
@Override
public void run() {
results = new ArrayList<>();
// Do tasks one by one
for (final String url :
urls) {
//Here the result is a String. Change "String" in the following two lines for other datatypes.
final ThreadLockedTask<String> task = new ThreadLockedTask<>();
final String imagePath = task.execute(new Runnable() {
@Override
public void run() {
//Start the task here
ImageDownloader.getInstance(listener).download(url,
new ImageDownloader.ImageDownloadCallback() {
@Override
public void onSuccess(String imagePath) {
//Set the result on success
task.setResult(imagePath);
}
@Override
public void onFailure() {
//Set result as null on failure
task.setResult(null);
}
});
}
});
if (imagePath!=null)
results.add(imagePath);
}
afterCallbacks();
}
}).start();
}
private PauseModeCallbackHandler() {}
private static void afterCallbacks() {
// All tasks completed. List "results" now holds the result
DemoActivity.isTasksInProgress = false;
}
}
从上一个回调中执行任务,就像连锁反应一样。
import java.util.ArrayList;
import java.util.List;
public class ChainModeCallbackHandler implements ImageDownloader.ImageDownloadCallback {
// List of args to start the task. Use pojo classes if your task has multiple args
private static List<String> urls;
// List of results
private static List<String> results;
// Optional.
private static ImageDownloader.ProgressUpdateListener progressUpdateListener;
// Leave it as it is
private int index;
public static void start(List<String> urls, ImageDownloader.ProgressUpdateListener listener) {
ChainModeCallbackHandler.urls = urls;
results = new ArrayList<>();
progressUpdateListener = listener;
//Start with the first task
ImageDownloader.getInstance(listener).download(urls.get(0), new ChainModeCallbackHandler(0));
}
private ChainModeCallbackHandler(int index) {
this.index = index;
}
@Override
public void onSuccess(String imagePath) {
results.add(imagePath);
afterCallback();
}
@Override
public void onFailure() {
afterCallback();
}
private void afterCallback() {
int nextIndex = index+1;
if (nextIndex<urls.size()) {
//Tasks are not completed yet. Do next task
ImageDownloader.getInstance(progressUpdateListener).download(urls.get(nextIndex),
new ChainModeCallbackHandler(nextIndex));
} else {
// All tasks completed. List "results" now holds the result
DemoActivity.isTasksInProgress = false;
}
}
}
并行执行任务。
专业人士
并行执行有时可以节省时间
import java.util.ArrayList;
import java.util.List;
public class ParallelModeCallbackHandler {
// List of args to start the task. Use pojo classes if your task has multiple args
private static List<String> urls;
// List of results
private static List<String> results;
// Leave it as it is
private static int count;
public static void start(List<String> urls, ImageDownloader.ProgressUpdateListener listener) {
ParallelModeCallbackHandler.urls = urls;
results = new ArrayList<>();
count = 0;
// Start all tasks
for (String url :
urls) {
//Replace with your task and its callback
ImageDownloader.getInstance(listener).download(url, new ImageDownloader.ImageDownloadCallback() {
@Override
public void onSuccess(String imagePath) {
results.add(imagePath);
afterCallback();
}
@Override
public void onFailure() {
afterCallback();
}
});
}
}
private ParallelModeCallbackHandler() {}
private static void afterCallback() {
if (++count==urls.size()) {
// All tasks completed. List "results" now holds the result
DemoActivity.isTasksInProgress = false;
}
}
}